home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / ref.c < prev    next >
C/C++ Source or Header  |  1993-03-31  |  70KB  |  3,005 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <sys/types.h>
  23. #include <signal.h>
  24. #include "sysdef.h"
  25. #include "global.h"
  26. #include "cell.h"
  27. #include "eval.h"
  28. #include "io-abstract.h"
  29. #include "io-generic.h"
  30. #include "hash.h"
  31. #include "byte-compile.h"
  32. #include "parse.h"
  33. #include "ref.h"
  34. #include "cmd.h"
  35.  
  36.  
  37. #ifdef __STDC__
  38. static void add_ref_fm (struct ref_fm **, CELLREF, CELLREF);
  39. static void flush_ref_fm (struct ref_fm **, CELLREF, CELLREF);
  40. static void flush_range_ref (struct rng *, CELLREF, CELLREF);
  41. extern void shift_formula (int r, int c, int dn, int ov);
  42. #ifdef SPLIT_REFS
  43. /* These two are tunable paramaters */
  44. #define REF_START    3
  45. #define REF_INC        *=2
  46. #else
  47. static void flush_ref_to (struct ref_to **);
  48. static void flush_fm_ref (struct ref_fm *);
  49. #endif /* SPLIT_REFS */
  50.  
  51. #else /* !__STDC__ */
  52.  
  53. static void add_ref_fm ();
  54. static void flush_ref_fm ();
  55. static void flush_range_ref ();
  56. extern void shift_formula ();
  57.  
  58. #ifdef SPLIT_REFS
  59. /* These two are tunable paramaters */
  60. #define REF_START    3
  61. #define REF_INC        *=2
  62. #else
  63. static void flush_ref_to ();
  64. static void flush_fm_ref ();
  65. #endif /* SPLIT_REFS */
  66. #endif /* __STDC__ */
  67.  
  68. /* More tunable paramaters */
  69.  
  70. #define FIFO_START    40
  71. #define FIFO_INC    *=2
  72.  
  73. #define TO_MAGIC(row,col)    (((long)(row)<<BITS_PER_CELLREF)|(col))
  74. #define MAGIC_ROW(magic)    (((magic)>>BITS_PER_CELLREF)&CELLREF_MASK)
  75. #define MAGIC_COL(magic)    ((magic)&CELLREF_MASK)
  76.  
  77. #define BETWEEN(mid,lo,hi)    ((mid>=lo)&&(mid<=hi))
  78.  
  79. static VOIDSTAR moving;
  80.  
  81. int timer_active = 0;
  82. struct ref_fm *timer_cells;
  83.  
  84. CELL *my_cell;
  85.  
  86. #ifdef TEST
  87. extern int debug;
  88. #endif
  89.  
  90. /* Functions for dealing exclusively with variables */
  91. struct hash_control *the_vars;
  92.  
  93. struct value
  94.   {
  95.     int type;
  96.     union vals c_z;
  97.   };
  98.  
  99. /* For the fifo-buffer */
  100. struct pos
  101.   {
  102.     CELLREF row;
  103.     CELLREF col;
  104.   };
  105.  
  106. struct cell_buf
  107.   {
  108.     unsigned int size;
  109.     struct pos *buf;
  110.     struct pos *push_to_here;
  111.     struct pos *pop_frm_here;
  112.   };
  113.  
  114.  
  115. /* Set the cell ROW,COL to STRING, parsing string as needed */
  116. #ifdef __STDC__
  117. void
  118. set_cell (CELLREF row, CELLREF col, char *string)
  119. #else
  120. void
  121. set_cell (row, col, string)
  122.      CELLREF row;
  123.      CELLREF col;
  124.      char *string;
  125. #endif
  126. {
  127.   unsigned char *ret;
  128.  
  129.   cur_row = row;
  130.   cur_col = col;
  131.  
  132. #ifdef TEST
  133.   if (!string)
  134.     {
  135.       io_error_msg ("Null string to set_cell %s", cell_name (row, col));
  136.       return;
  137.     }
  138. #endif
  139.   while (*string == ' ')
  140.     string++;
  141.  
  142.   if (!*string)
  143.     {
  144.       my_cell = find_cell (cur_row, cur_col);
  145.       if (!my_cell)
  146.     return;
  147.       flush_old_value ();
  148.       return;
  149.     }
  150.  
  151.   my_cell = find_or_make_cell (cur_row, cur_col);
  152.   flush_old_value ();
  153.  
  154.   ret = parse_and_compile (string);
  155.   my_cell->cell_formula = ret;
  156. }
  157.  
  158. extern int default_lock;
  159.  
  160. /* new_value() calls set_cell, but refuses to change locked cells, and
  161.    updates and prints the results.  It returns an error msg on error. . .
  162.  */
  163. #ifdef __STDC__
  164. char *
  165. new_value (CELLREF row, CELLREF col, char *string)
  166. #else
  167. char *
  168. new_value (row, col, string)
  169.      CELLREF row;
  170.      CELLREF col;
  171.      char *string;
  172. #endif
  173. {
  174.   CELL *cp;
  175.  
  176.   cp = find_cell (row, col);
  177.   if (((!cp || GET_LCK (cp) == LCK_DEF) && default_lock == LCK_LCK) || (cp && GET_LCK (cp) == LCK_LCK))
  178.     {
  179.       return "cell is locked";
  180.     }
  181.  
  182.   set_cell (row, col, string);
  183.   if (my_cell)
  184.     {
  185.       update_cell (my_cell);
  186.       if (is_constant (my_cell->cell_formula))
  187.     {
  188.       byte_free (my_cell->cell_formula);
  189.       my_cell->cell_formula = 0;
  190.     }
  191.       io_pr_cell (row, col, my_cell);
  192.       my_cell = 0;
  193.     }
  194.   return 0;
  195. }
  196.  
  197. /* This sets the cell to a constant, stored in VALUE, whose type is in TYPE */
  198. #ifdef __STDC__
  199. char *
  200. set_new_value (CELLREF row, CELLREF col, int type, union vals *value)
  201. #else
  202. char *
  203. set_new_value (row, col, type, value)
  204.      CELLREF row;
  205.      CELLREF col;
  206.      int type;
  207.      union vals *value;
  208. #endif
  209. {
  210.   CELL *cp;
  211.   extern int default_lock;
  212.  
  213.   if (type == TYP_ERR)
  214.     type = 0;
  215.   cur_row = row;
  216.   cur_col = col;
  217.   if (type == 0)
  218.     {
  219.       cp = find_cell (row, col);
  220.       if (cp && GET_TYP (cp))
  221.     {
  222.       if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  223.         return "cell is locked";
  224.       my_cell = cp;
  225.       flush_old_value ();
  226.       SET_TYP (cp, 0);
  227.     }
  228.       my_cell = 0;
  229.       return 0;
  230.     }
  231.   else
  232.     {
  233.       cp = find_or_make_cell (row, col);
  234.       if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  235.     return "cell is locked";
  236.       my_cell = cp;
  237.       flush_old_value ();
  238.       SET_TYP (cp, type);
  239.       /* cp->c_z= *value; */
  240.       switch (type)
  241.     {
  242.     case TYP_FLT:
  243.       cp->cell_flt = value->c_d;
  244.       cp->cell_formula = 0;
  245.       break;
  246.  
  247.     case TYP_INT:
  248.       cp->cell_int = value->c_l;
  249.       cp->cell_formula = 0;
  250.       break;
  251.  
  252.     case TYP_STR:
  253.       cp->cell_str = strdup (value->c_s);
  254.       cp->cell_formula = 0;
  255.       break;
  256.  
  257.     case TYP_BOL:
  258.       cp->cell_bol = value->c_i;
  259.       cp->cell_formula = 0;
  260.       break;
  261.  
  262.     case TYP_ERR:
  263.       cp->cell_err = value->c_i;
  264.       cp->cell_formula = 0;
  265.       break;
  266. #ifdef TEST
  267.     default:
  268.       panic ("Unknown type %d in set_new_value", GET_TYP (cp));
  269. #endif
  270.     }
  271.     }
  272.   push_refs (cp->cell_refs_from);
  273.   io_pr_cell (row, col, cp);
  274.   my_cell = 0;
  275.   return 0;
  276. }
  277.  
  278. /* We're reading in a cell, whose formula is FORM, and whose current value
  279.    is VAL.  Parse both of them. . .  (Parsing of VAL is quite primitive)
  280.  */
  281. #ifdef __STDC__
  282. char *
  283. read_new_value (CELLREF row, CELLREF col, char *form, char *val)
  284. #else
  285. char *
  286. read_new_value (row, col, form, val)
  287.      CELLREF row;
  288.      CELLREF col;
  289.      char *form;
  290.      char *val;
  291. #endif
  292. {
  293.   unsigned char *new_bytes;
  294.   extern double __plinf, __neinf, __nan;
  295.  
  296.   cur_row = row;
  297.   cur_col = col;
  298.   my_cell = find_or_make_cell (cur_row, cur_col);
  299.   flush_old_value ();
  300.   SET_TYP (my_cell, 0);
  301.  
  302.   if (form)
  303.     {
  304.       new_bytes = parse_and_compile (form);
  305.       my_cell->cell_formula = new_bytes;
  306.     }
  307.  
  308.   if (val)
  309.     {
  310.       if (val[0] == '"')
  311.     {
  312.       char *sp, *nsp;
  313.  
  314.       sp = val + 1;
  315.       SET_TYP (my_cell, TYP_STR);
  316.       while (*sp)
  317.         sp++;
  318.       if (*--sp != '"')
  319.         {
  320.           if (*sp == '\r' && sp[-1] == '"')
  321.         --sp;
  322.           else
  323.         panic ("Can't find \" in read_new value");
  324.         }
  325.       *sp = '\0';
  326.       nsp = my_cell->cell_str = ck_malloc (sp - val);
  327.       for (sp = val + 1; *sp;)
  328.         *nsp++ = *sp++;
  329.       *nsp++ = '\0';
  330.     }
  331.       else if (isdigit (val[0]) || val[0] == '.' || val[0] == '-' || val[0] == '+')
  332.     {
  333.       char *v;
  334.  
  335.       v = val;
  336.       SET_TYP (my_cell, TYP_INT);
  337.       my_cell->cell_int = astol (&v);
  338.       if (*v)
  339.         {
  340.           SET_TYP (my_cell, TYP_FLT);
  341.           v = val;
  342.           my_cell->cell_flt = astof (&v);
  343.           if (*v)
  344.         return "unknown number";
  345.         }
  346.     }
  347.       else if (val[0] == '#')
  348.     {
  349.       char **en;
  350.  
  351.       if (!stricmp (tname, val))
  352.         {
  353.           SET_TYP (my_cell, TYP_BOL);
  354.           my_cell->cell_bol = 1;
  355.         }
  356.       else if (!stricmp (fname, val))
  357.         {
  358.           SET_TYP (my_cell, TYP_BOL);
  359.           my_cell->cell_bol = 0;
  360.         }
  361.       else if (!stricmp (iname, val))
  362.         {
  363.           SET_TYP (my_cell, TYP_FLT);
  364.           my_cell->cell_flt = __plinf;
  365.         }
  366.       else if (!stricmp (iname, val))
  367.         {
  368.           SET_TYP (my_cell, TYP_FLT);
  369.           my_cell->cell_flt = __plinf;
  370.         }
  371.       else if (!stricmp (mname, val))
  372.         {
  373.           SET_TYP (my_cell, TYP_FLT);
  374.           my_cell->cell_flt = __neinf;
  375.         }
  376.       else if (!stricmp (nname, val))
  377.         {
  378.           SET_TYP (my_cell, TYP_FLT);
  379.           my_cell->cell_flt = __nan;
  380.         }
  381.       else
  382.         {
  383.           SET_TYP (my_cell, TYP_ERR);
  384.           for (en = ename; *en; en++)
  385.         if (!stricmp (*en, val))
  386.           break;
  387.           if (*en)
  388.         my_cell->cell_err = en - &ename[0];
  389.           else
  390.         my_cell->cell_err = 1;
  391.         }
  392.     }
  393.       else
  394.     panic ("What is a '%s'?", val);
  395.     }
  396.  
  397.   my_cell = 0;
  398.   return 0;
  399. }
  400.  
  401. /* This moves the contents, format, etc from RF,CF to RT,CT  RF or RT may be
  402.    NON_ROW, in which case the cell's contents are moved to/from a static
  403.    storage area.  Moving anything from NON_ROW before moving anything into it
  404.    or moving two things at a time into NON_ROW are both bad ideas. . .
  405.  
  406.    Also note that move_cell does not call move_outside, which may or may not
  407.    be a bug. . .  Move_cell is only called as part of sorting, which is why
  408.    we may *not* want to call move_outside. . .
  409.  */
  410.  
  411. #ifdef __STDC__
  412. void
  413. move_cell (CELLREF rf, CELLREF cf, CELLREF rt, CELLREF ct)
  414. #else
  415. void
  416. move_cell (rf, cf, rt, ct)
  417.      CELLREF rf;
  418.      CELLREF cf;
  419.      CELLREF rt;
  420.      CELLREF ct;
  421. #endif
  422. {
  423.   CELL *cpf;
  424.  
  425.   static CELLREF non_rf, non_cf;
  426.   static struct cell non_cell;
  427.  
  428.   if (rf == NON_ROW)
  429.     {
  430.       cur_row = rt;
  431.       cur_col = ct;
  432.       my_cell = find_cell (cur_row, cur_col);
  433.       if (my_cell)
  434.     flush_old_value ();
  435.       else if (!non_cell.cell_flags && !non_cell.cell_formula
  436.            && !non_cell.cell_font)
  437.     return;
  438.       else
  439.     my_cell = find_or_make_cell (cur_row, cur_col);
  440.  
  441.       my_cell->cell_flags = non_cell.cell_flags;
  442.       my_cell->cell_refs_to = non_cell.cell_refs_to;
  443.       my_cell->cell_formula = non_cell.cell_formula;
  444.       my_cell->cell_cycle = non_cell.cell_cycle;
  445.       my_cell->cell_font = non_cell.cell_font;
  446.       my_cell->c_z = non_cell.c_z;
  447.       push_refs (my_cell->cell_refs_from);
  448.       if (my_cell->cell_refs_to)
  449.     shift_formula (cur_row, cur_col, rt - non_rf, ct - non_cf);
  450.       my_cell = 0;
  451.       return;
  452.     }
  453.  
  454.   cpf = find_cell (rf, cf);
  455.  
  456.   if (rt == NON_ROW)
  457.     {
  458.       non_rf = rf;
  459.       non_cf = cf;
  460.       if (!cpf)
  461.     bzero (&non_cell, sizeof (non_cell));
  462.       else
  463.     {
  464.       non_cell.cell_flags = cpf->cell_flags;
  465.       non_cell.cell_refs_to = cpf->cell_refs_to;
  466.       non_cell.cell_formula = cpf->cell_formula;
  467.       non_cell.cell_cycle = cpf->cell_cycle;
  468.       non_cell.cell_font = cpf->cell_font;
  469.       non_cell.c_z = cpf->c_z;
  470.       cpf->cell_flags = 0;
  471.       cpf->cell_refs_to = 0;
  472.       cpf->cell_formula = 0;
  473.       cpf->cell_cycle = 0;
  474.       cpf->cell_font = 0;
  475.     }
  476.       return;
  477.     }
  478.  
  479.   cur_row = rt;
  480.   cur_col = ct;
  481.   my_cell = find_cell (cur_row, cur_col);
  482.   if ((!cpf || (!cpf->cell_flags && !cpf->cell_formula && !cpf->cell_font))
  483.       && !my_cell)
  484.     return;
  485.   if (!my_cell)
  486.     {
  487.       my_cell = find_or_make_cell (cur_row, cur_col);
  488.       cpf = find_cell (rf, cf);    /* FOO */
  489.     }
  490.   else
  491.     flush_old_value ();
  492.  
  493.   if (!cpf)
  494.     return;
  495.  
  496.   my_cell->cell_flags = cpf->cell_flags;
  497.   my_cell->cell_refs_to = cpf->cell_refs_to;
  498.   my_cell->cell_formula = cpf->cell_formula;
  499.   my_cell->cell_cycle = cpf->cell_cycle;
  500.   my_cell->cell_font = cpf->cell_font;
  501.   my_cell->c_z = cpf->c_z;
  502.  
  503.   cpf->cell_flags = 0;
  504.   cpf->cell_refs_to = 0;
  505.   cpf->cell_formula = 0;
  506.   cpf->cell_cycle = 0;
  507.   cpf->cell_font = 0;
  508.  
  509.   push_refs (my_cell->cell_refs_from);
  510.   if (my_cell->cell_refs_to)
  511.     shift_formula (cur_row, cur_col, rt - rf, ct - cf);
  512.   my_cell = 0;
  513. }
  514.  
  515. #ifdef __STDC__
  516. void
  517. copy_cell (CELLREF rf, CELLREF cf, CELLREF rt, CELLREF ct)
  518. #else
  519. void
  520. copy_cell (rf, cf, rt, ct)
  521.      CELLREF rf;
  522.      CELLREF cf;
  523.      CELLREF rt;
  524.      CELLREF ct;
  525. #endif
  526. {
  527.   CELL *cpf;
  528.  
  529.   cpf = find_cell (rf, cf);
  530.   cur_row = rt;
  531.   cur_col = ct;
  532.   my_cell = find_cell (cur_row, cur_col);
  533.   if ((!cpf || (!cpf->cell_flags && !cpf->cell_formula && !cpf->cell_font))
  534.       && !my_cell)
  535.     return;
  536.   if (!my_cell)
  537.     {
  538.       my_cell = find_or_make_cell (cur_row, cur_col);
  539.       cpf = find_cell (rf, cf);    /* FOO */
  540.     }
  541.   else
  542.     flush_old_value ();
  543.  
  544.   if (!cpf)
  545.     return;
  546.  
  547.   my_cell->cell_flags = cpf->cell_flags;
  548.   my_cell->cell_cycle = cpf->cell_cycle;
  549.   my_cell->cell_font = cpf->cell_font;
  550.   my_cell->cell_refs_to = cpf->cell_refs_to;
  551.  
  552.   if (my_cell->cell_refs_to)
  553.     my_cell->cell_refs_to->refs_refcnt++;
  554.  
  555.   if (GET_TYP (my_cell) == TYP_STR)
  556.     my_cell->cell_str = strdup (cpf->cell_str);
  557.   else
  558.     my_cell->c_z = cpf->c_z;
  559.  
  560.   if (cpf->cell_formula)
  561.     {
  562.       unsigned char *fp;
  563.       unsigned char *hi;
  564.       unsigned char byte;
  565.       CELLREF trr, tcc;
  566.       struct rng trng;
  567.       struct function *f;
  568.       size_t len;
  569.       struct var *v;
  570.       CELL *tcp;
  571.  
  572.       fp = cpf->cell_formula;
  573.       hi = 0;
  574.       if (!moving)
  575.     moving = init_stack ();
  576.       while ((byte = *fp++) != ENDCOMP)
  577.     {
  578.       unsigned char * refloc = fp - 1;
  579.       if (byte < USR1)
  580.         f = &the_funs[byte];
  581.       else if (byte < SKIP)
  582.         {
  583.           int tmp;
  584. #ifdef TEST
  585.           if (byte - USR1 >= n_usr_funs)
  586.         panic ("Only have %d usr-function slots, but found byte for slot %d", n_usr_funs, 1 + byte - USR1);
  587. #endif
  588.           tmp = *fp++;
  589.           f = &usr_funs[byte - USR1][tmp];
  590.         }
  591.       else
  592.         f = &skip_funs[byte - SKIP];
  593.  
  594.       if (f->fn_argn & X_J)
  595.         fp++;
  596.       else if (f->fn_argn & X_JL)
  597.         fp += 2;
  598.  
  599.       if ((f->fn_argn & X_ARGS) == X_AN)
  600.         fp++;
  601.  
  602.       switch (byte)
  603.         {
  604.         case CONST_FLT:
  605.           fp += sizeof (double);
  606.           break;
  607.  
  608.         case CONST_INT:
  609.           fp += sizeof (long);
  610.           break;
  611.  
  612.         case CONST_STR:
  613.           if (!hi)
  614.         hi = fp + fp[-1];
  615.           break;
  616.  
  617.         case CONST_STR_L:
  618.           if (!hi)
  619.         hi = fp + fp[-2] + ((unsigned) (fp[-1]) << 8);
  620.           break;
  621.  
  622.         case CONST_ERR:
  623.           fp += 1 /* +sizeof(char *) */ ;
  624.           break;
  625.  
  626.         case VAR:
  627.           bcopy (fp, &v, sizeof (struct var *));
  628.           fp += sizeof (struct var *);
  629.           add_ref_fm (&(v->var_ref_fm), cur_row, cur_col);
  630.           switch (v->var_flags)
  631.         {
  632.         case VAR_UNDEF:
  633.           break;
  634.         case VAR_CELL:
  635.           tcp = find_cell (v->v_rng.lr, v->v_rng.lc);
  636.           add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  637.           break;
  638.         case VAR_RANGE:
  639.           add_range_ref (&(v->v_rng));
  640.           /* sparse array bug fixed here */
  641.           my_cell = find_cell (cur_row, cur_col);
  642.           cpf = find_cell (rf, cf);
  643.           break;
  644.         }
  645.           break;
  646.  
  647.         case R_CELL:
  648.         case R_CELL | COLREL:
  649.         case R_CELL | ROWREL:
  650.         case R_CELL | ROWREL | COLREL:
  651.           push_stack (moving, fp);
  652.           fp += EXP_ADD;
  653.           break;
  654.  
  655.         case RANGE:
  656.         case RANGE | LRREL:
  657.         case RANGE | LRREL | LCREL:
  658.         case RANGE | LRREL | LCREL | HCREL:
  659.         case RANGE | LRREL | HCREL:
  660.         case RANGE | LRREL | HRREL:
  661.         case RANGE | LRREL | HRREL | LCREL:
  662.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  663.         case RANGE | LRREL | HRREL | HCREL:
  664.         case RANGE | HRREL:
  665.         case RANGE | HRREL | LCREL:
  666.         case RANGE | HRREL | LCREL | HCREL:
  667.         case RANGE | HRREL | HCREL:
  668.         case RANGE | LCREL:
  669.         case RANGE | LCREL | HCREL:
  670.         case RANGE | HCREL:
  671.           push_stack (moving, fp);
  672.           fp += EXP_ADD_RNG;
  673.           break;
  674.  
  675.         default:
  676.           {
  677.         struct function *fun;
  678.  
  679.         if (byte >= SKIP)
  680.           break;
  681.         
  682.         if (byte < USR1)
  683.           fun = &the_funs[byte];
  684.         else
  685.            fun = &usr_funs[byte - USR1][refloc[1]];
  686.         
  687.         if (fun->fn_comptype & C_T)
  688.           {
  689.             add_ref_fm (&timer_cells, rt, ct);
  690.             ++timer_active;
  691.           }
  692.         break;
  693.           }
  694.         }
  695.     }
  696.       if (!hi)
  697.     hi = fp;
  698.       else
  699.     hi += strlen ((char *) hi);
  700.       hi++;
  701.       len = hi - cpf->cell_formula;
  702.       my_cell->cell_formula = cpf->cell_formula;
  703.       cpf->cell_formula = ck_malloc (hi - cpf->cell_formula);
  704.       bcopy (my_cell->cell_formula, cpf->cell_formula, len);
  705.       while (fp = pop_stack (moving))
  706.     {
  707.       byte = fp[-1];
  708.       if ((byte | ROWREL | COLREL) == (R_CELL | ROWREL | COLREL))
  709.         {
  710.           trr = GET_ROW (fp);
  711.           tcc = GET_COL (fp);
  712.           if (byte & ROWREL)
  713.         {
  714.           trr += rt - rf;
  715.           PUT_ROW (fp, trr);
  716.         }
  717.           if (byte & COLREL)
  718.         {
  719.           tcc += ct - cf;
  720.           PUT_COL (fp, tcc);
  721.         }
  722.           tcp = find_or_make_cell (trr, tcc);
  723.           add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  724.         }
  725. #ifdef TEST
  726.       else if ((byte | LRREL | HRREL | LCREL | HCREL) !=
  727.            (RANGE | LRREL | HRREL | LCREL | HCREL))
  728.         panic ("Unknown byte %x in copy_cell", byte);
  729. #endif
  730.       else
  731.         {
  732.           GET_RNG (fp, &trng);
  733.           if (byte & LRREL)
  734.         trng.lr += rt - rf;
  735.           if (byte & HRREL)
  736.         trng.hr += rt - rf;
  737.           if (byte & LCREL)
  738.         trng.lc += ct - cf;
  739.           if (byte & HCREL)
  740.         trng.hc += ct - cf;
  741.           PUT_RNG (fp, &trng);
  742.           add_range_ref (&trng);
  743.           /* sparse array bug fixed here */
  744.           my_cell = find_cell (cur_row, cur_col);
  745.           cpf = find_cell (rf, cf);
  746.         }
  747.     }
  748.       update_cell (my_cell);
  749.     }
  750.   else
  751.     {
  752.       my_cell->cell_formula = 0;
  753.     }
  754.   io_pr_cell (cur_row, cur_col, my_cell);
  755.  
  756.   push_refs (my_cell->cell_refs_from);
  757.   my_cell = 0;
  758. }
  759.  
  760. /* Take away the value of CP.  This means getting rid of all the references
  761.    to it, etc.
  762.  */
  763. #ifdef __STDC__
  764. void
  765. flush_old_value (void)
  766. #else
  767. void
  768. flush_old_value ()
  769. #endif
  770. {
  771.   struct ref_to *ref;
  772.   unsigned char *refloc;
  773.   int n;
  774.   unsigned char byte;
  775.   CELL *other_cell;
  776.   struct var *varp;
  777.  
  778.   ref = my_cell->cell_refs_to;
  779.   if (ref)
  780.     {
  781.       for (n = 0; n < ref->refs_used; n++)
  782.     {
  783.       /* Switch on formula[ref->to_refs[n]] */
  784.       refloc = &(my_cell->cell_formula[ref->to_refs[n]]);
  785.       byte = refloc[0];
  786.       switch (byte)
  787.         {
  788.         case F_ROW:
  789.         case F_COL:
  790.           break;
  791.  
  792.         case R_CELL:
  793.         case R_CELL | ROWREL:
  794.         case R_CELL | COLREL:
  795.         case R_CELL | ROWREL | COLREL:
  796.           other_cell = find_cell (GET_ROW (refloc + 1), GET_COL (refloc + 1));
  797.           if (other_cell)
  798.         flush_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  799. #ifdef TEST
  800.           else
  801.         io_error_msg ("Can't find other_cell in flush_old_value");
  802. #endif
  803.           break;
  804.         case RANGE:
  805.         case RANGE | LRREL:
  806.         case RANGE | LRREL | LCREL:
  807.         case RANGE | LRREL | LCREL | HCREL:
  808.         case RANGE | LRREL | HCREL:
  809.         case RANGE | LRREL | HRREL:
  810.         case RANGE | LRREL | HRREL | LCREL:
  811.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  812.         case RANGE | LRREL | HRREL | HCREL:
  813.         case RANGE | HRREL:
  814.         case RANGE | HRREL | LCREL:
  815.         case RANGE | HRREL | LCREL | HCREL:
  816.         case RANGE | HRREL | HCREL:
  817.         case RANGE | LCREL:
  818.         case RANGE | LCREL | HCREL:
  819.         case RANGE | HCREL:
  820.           {
  821.         struct rng rng;
  822.  
  823.         GET_RNG (refloc + 1, &rng);
  824.         flush_range_ref (&rng, cur_row, cur_col);
  825.           }
  826.           break;
  827.  
  828.         case VAR:
  829.           bcopy (&refloc[1], &varp, sizeof (struct var *));
  830.           flush_ref_fm (&(varp->var_ref_fm), cur_row, cur_col);
  831.           if (varp->var_flags == VAR_CELL)
  832.         {
  833.           other_cell = find_cell (varp->v_rng.lr, varp->v_rng.lc);
  834.           if (other_cell)
  835.             flush_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  836.         }
  837.           else if (varp->var_flags == VAR_RANGE)
  838.         flush_range_ref (&(varp->v_rng), cur_row, cur_col);
  839. #ifdef TEST
  840.           else if (varp->var_flags != VAR_UNDEF)
  841.         panic ("Unknown var type %d", varp->var_flags);
  842. #endif
  843.           break;
  844.  
  845.         default:
  846.           {
  847.         struct function *fun;
  848.  
  849.         if (byte < USR1)
  850.           fun = &the_funs[byte];
  851. #ifdef TEST
  852.         else if (byte >= SKIP)
  853.           fun = 0, panic ("SKIP? in flush_old_value()");
  854. #endif
  855.         else
  856.           fun = &usr_funs[byte - USR1][refloc[1]];
  857.  
  858.         if (fun->fn_comptype & C_T)
  859.           {
  860. #ifdef TEST
  861.             if (!timer_cells || !timer_cells->refs_used)
  862.               panic ("No timer cells in flush_timer_cell");
  863. #endif
  864.             flush_ref_fm (&timer_cells, cur_row, cur_col);
  865.             --timer_active;
  866.             break;
  867.           }
  868.         else
  869.           io_error_msg ("Bad ref_to of %d.%x ignored", ref->to_refs[n], byte);
  870.           }
  871.           break;
  872.         }
  873.     }
  874. #ifdef SPLIT_REFS
  875.       ref->refs_used = 0;
  876. #else
  877.       flush_ref_to (&(my_cell->cell_refs_to));
  878. #endif
  879.     }
  880.   if (my_cell->cell_formula)
  881.     {
  882.       byte_free (my_cell->cell_formula);
  883.       my_cell->cell_formula = 0;
  884.     }
  885.   if (GET_TYP (my_cell) == TYP_STR)
  886.     free (my_cell->cell_str);
  887.   SET_TYP (my_cell, 0);
  888. }
  889.  
  890. /* --------- Routines for dealing with cell references to other cells ------ */
  891.  
  892. #ifdef __STDC__
  893. void
  894. add_ref (CELLREF row, CELLREF col)
  895. #else
  896. void
  897. add_ref (row, col)
  898.      CELLREF row;
  899.      CELLREF col;
  900. #endif
  901. {
  902.   CELL *other_cell;
  903.  
  904.   other_cell = find_or_make_cell (row, col);
  905.   add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  906. }
  907.  
  908. #ifdef __STDC__
  909. void
  910. add_range_ref (struct rng *rng)
  911. #else
  912. void
  913. add_range_ref (rng)
  914.      struct rng *rng;
  915. #endif
  916. {
  917.   CELL *other_cell;
  918.   struct ref_fm *oldref, *newref;
  919.   struct ref_fm nonref;
  920.  
  921.  
  922.   make_cells_in_range (rng);
  923.  
  924.   /* Be efficient:  If cells in the range currently have the same
  925.    * references, they'll have the same references afterward, so just
  926.    * adjust the refcounts
  927.    */
  928.   nonref.refs_refcnt = 1;
  929.   other_cell = next_cell_in_range ();
  930.   oldref = other_cell->cell_refs_from;
  931.   if (oldref && oldref->refs_refcnt == 1)
  932.     oldref = &nonref;
  933.  
  934.   add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  935.   newref = other_cell->cell_refs_from;
  936.   while (other_cell = next_cell_in_range ())
  937.     {
  938.       if (other_cell->cell_refs_from == oldref)
  939.     {
  940.       if (oldref)
  941.         {
  942.           if (oldref->refs_refcnt == 1)
  943.         {
  944.           flush_fm_ref (oldref);
  945.           oldref = &nonref;
  946.         }
  947.           else
  948.         oldref->refs_refcnt--;
  949.         }
  950.       other_cell->cell_refs_from = newref;
  951.       newref->refs_refcnt++;
  952.     }
  953.       else if (oldref == &nonref && (!other_cell->cell_refs_from || other_cell->cell_refs_from->refs_refcnt > 1))
  954.     {
  955.       oldref = other_cell->cell_refs_from;
  956.       add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  957.       newref = other_cell->cell_refs_from;
  958.     }
  959.       else
  960.     add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  961.     }
  962.   /* if(oldref && oldref->refs_refcnt==0) {
  963.         oldref->refs_refcnt=1;
  964.         flush_fm_ref(oldref);
  965.     } */
  966. }
  967.  
  968. #ifdef __STDC__
  969. static void
  970. flush_range_ref (struct rng *rng, CELLREF rr, CELLREF cc)
  971. #else
  972. static void
  973. flush_range_ref (rng, rr, cc)
  974.      struct rng *rng;
  975.      CELLREF rr;
  976.      CELLREF cc;
  977. #endif
  978. {
  979.   CELL *other_cell;
  980. #ifndef SPLIT_REFS
  981.   struct ref_fm *oldref, *newref;
  982.   struct ref_fm nonref;
  983. #endif
  984.   /* This is horribly inefficient:  Simply referencing a cell makes
  985.        it appear.  On the other hand, there is no other easy way to deal
  986.        with the references to the cells (That I know of, anyway) */
  987.   find_cells_in_range (rng);
  988. #ifndef SPLIT_REFS
  989.   /* Be efficient:  If cells in the range currently have the same
  990.        references, they'll have the same references afterward, so just
  991.        adjust the refcounts */
  992.   nonref.refs_refcnt = 1;
  993.   other_cell = next_cell_in_range ();
  994.   if (!other_cell)
  995.     return;
  996.   oldref = other_cell->cell_refs_from;
  997.   if (oldref && oldref->refs_refcnt == 1)
  998.     oldref = &nonref;
  999.  
  1000.   flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1001.   newref = other_cell->cell_refs_from;
  1002.   while (other_cell = next_cell_in_range ())
  1003.     {
  1004.       if (other_cell->cell_refs_from == oldref)
  1005.     {
  1006.       if (oldref)
  1007.         {
  1008.           if (oldref->refs_refcnt == 1)
  1009.         {
  1010.           flush_fm_ref (oldref);
  1011.           oldref = &nonref;
  1012.         }
  1013.           else
  1014.         oldref->refs_refcnt--;
  1015.         }
  1016.       other_cell->cell_refs_from = newref;
  1017.       if (newref)
  1018.         newref->refs_refcnt++;
  1019.     }
  1020.       else if (oldref == &nonref && (!other_cell->cell_refs_from || other_cell->cell_refs_from->refs_refcnt > 1))
  1021.     {
  1022.       oldref = other_cell->cell_refs_from;
  1023.       flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1024.       newref = other_cell->cell_refs_from;
  1025.     }
  1026.       else
  1027.     flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1028.     }
  1029. #else
  1030.   while (other_cell = next_cell_in_range ())
  1031.     flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1032. #endif
  1033. }
  1034.  
  1035. /* SPLIT_REFS should probably go away, since it is a performance loss.
  1036.    When it is defined, we allocate a a reference structure for each cell with
  1037.    references, and update them individually.
  1038.  
  1039.    The default is to allocate one reference structure for each *different*
  1040.    reference, and have multiple cells point to it.  We use reference counts
  1041.    to keep track of when to delete the reference structure.  This would
  1042.    appear to be a performance loss, but because of the increased efficiency
  1043.    in referencing ranges, it may actually be faster.  It also uses *far* less
  1044.    memory than SPLIT_REFS */
  1045.  
  1046.  
  1047. #ifndef SPLIT_REFS
  1048. #ifdef __TURBOC__
  1049. #define FM_HASH_NUM 51
  1050. #define TO_HASH_NUM 13
  1051. #else
  1052. #define FM_HASH_NUM 503
  1053. #define TO_HASH_NUM 29
  1054. #endif
  1055. #ifdef TEST
  1056. static int fm_misses = 0;
  1057. static int to_misses = 0;
  1058. #endif
  1059.  
  1060. static struct ref_fm *fm_list[FM_HASH_NUM];
  1061. static struct ref_fm *fm_tmp_ref;
  1062. static unsigned fm_tmp_ref_alloc;
  1063.  
  1064. static struct ref_to *to_list[TO_HASH_NUM];
  1065. static struct ref_to *to_tmp_ref;
  1066. static unsigned to_tmp_ref_alloc;
  1067.  
  1068. #ifdef __STDC__
  1069. void
  1070. flush_refs (void)
  1071. #else
  1072. void
  1073. flush_refs ()
  1074. #endif
  1075. {
  1076.   int n;
  1077.   struct ref_fm *ftmp, *oftmp;
  1078.   struct ref_to *ttmp, *ottmp;
  1079.  
  1080.   for (n = 0; n < FM_HASH_NUM; n++)
  1081.     {
  1082.       for (ftmp = fm_list[n]; ftmp; ftmp = oftmp)
  1083.     {
  1084.       oftmp = ftmp->refs_next;
  1085.       free (ftmp);
  1086.     }
  1087.       fm_list[n] = 0;
  1088.     }
  1089.   for (n = 0; n < TO_HASH_NUM; n++)
  1090.     {
  1091.       for (ttmp = to_list[n]; ttmp; ttmp = ottmp)
  1092.     {
  1093.       ottmp = ttmp->refs_next;
  1094.       free (ttmp);
  1095.     }
  1096.       to_list[n] = 0;
  1097.     }
  1098. }
  1099.  
  1100. #ifdef __STDC__
  1101. static struct ref_fm *
  1102. find_fm_ref (void)
  1103. #else
  1104. static struct ref_fm *
  1105. find_fm_ref ()
  1106. #endif
  1107. {
  1108.   struct ref_fm *tmp;
  1109.   int n;
  1110.   unsigned long hash;
  1111.  
  1112. #if 1
  1113.   for (hash = 0, n = 0; n < fm_tmp_ref->refs_used; n++)
  1114.     {
  1115.       hash += (n + 1) * (((fm_tmp_ref->fm_refs[n].ref_row) << BITS_PER_CELLREF) +
  1116.              fm_tmp_ref->fm_refs[n].ref_col);
  1117.     }
  1118.   hash %= FM_HASH_NUM;
  1119. #else
  1120.   hash = fm_tmp_ref->refs_used;
  1121. #endif
  1122.   for (tmp = fm_list[hash]; tmp; tmp = tmp->refs_next)
  1123.     {
  1124.       if (tmp->refs_used != fm_tmp_ref->refs_used)
  1125.     continue;
  1126.       if (!bcmp (tmp->fm_refs, fm_tmp_ref->fm_refs, fm_tmp_ref->refs_used * sizeof (struct ref_array)))
  1127.     {
  1128.       tmp->refs_refcnt++;
  1129.       return tmp;
  1130.     }
  1131. #ifdef TEST
  1132.       else
  1133.     fm_misses++;
  1134. #endif
  1135.     }
  1136.  
  1137.   tmp = ck_malloc (sizeof (struct ref_fm) + (fm_tmp_ref->refs_used - 1) * sizeof (struct ref_array));
  1138.   tmp->refs_next = fm_list[hash];
  1139.   fm_list[hash] = tmp;
  1140.   tmp->refs_refcnt = 1;
  1141.   tmp->refs_used = fm_tmp_ref->refs_used;
  1142.   bcopy (fm_tmp_ref->fm_refs, tmp->fm_refs, tmp->refs_used * sizeof (struct ref_array));
  1143.  
  1144.   return tmp;
  1145. }
  1146.  
  1147. #ifdef __STDC__
  1148. static void 
  1149. flush_fm_ref (struct ref_fm *old)
  1150. #else
  1151. static void 
  1152. flush_fm_ref (old)
  1153.      struct ref_fm *old;
  1154. #endif
  1155. {
  1156.   struct ref_fm *tmp;
  1157.   int n;
  1158.   unsigned long hash;
  1159.  
  1160.   --(old->refs_refcnt);
  1161.  
  1162. #ifdef DEFER_FREE
  1163.   return;
  1164. #endif
  1165.   if (!old->refs_refcnt)
  1166.     {
  1167. #if 1
  1168.       for (hash = 0, n = 0; n < old->refs_used; n++)
  1169.     {
  1170.       hash += (n + 1) * (((old->fm_refs[n].ref_row) << BITS_PER_CELLREF) +
  1171.                  old->fm_refs[n].ref_col);
  1172.     }
  1173.       hash %= FM_HASH_NUM;
  1174. #else
  1175.       hash = old->refs_used;
  1176. #endif
  1177.       if (fm_list[hash] == old)
  1178.     fm_list[hash] = old->refs_next;
  1179.       else
  1180.     {
  1181.       for (tmp = fm_list[hash]; tmp && tmp->refs_next != old; tmp = tmp->refs_next)
  1182.         ;
  1183. #ifdef TEST
  1184.       if (!tmp)
  1185.         {
  1186.           io_error_msg ("Old not in refs_list in flush_fm_ref(%p)", old);
  1187.           return;
  1188.         }
  1189. #endif
  1190.       tmp->refs_next = old->refs_next;
  1191.     }
  1192.       free (old);
  1193.     }
  1194. }
  1195.  
  1196. /* This adds a from reference to a cells reference list.
  1197.  * Note that the ref_fm structures themselves are hash-consed.
  1198.  */
  1199. #ifdef __STDC__
  1200. static void
  1201. add_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1202. #else
  1203. static void
  1204. add_ref_fm (where, r, c)
  1205.      struct ref_fm **where;
  1206.      CELLREF r;
  1207.      CELLREF c;
  1208. #endif
  1209. {
  1210.   struct ref_fm *from;
  1211.   int n;
  1212.  
  1213.   from = *where;
  1214.   if (!from)
  1215.     {
  1216.       if (!fm_tmp_ref)
  1217.     {
  1218.       fm_tmp_ref = ck_malloc (sizeof (struct ref_fm));
  1219.       fm_tmp_ref_alloc = 1;
  1220.     }
  1221.       fm_tmp_ref->refs_used = 1;
  1222.       fm_tmp_ref->fm_refs[0].ref_row = r;
  1223.       fm_tmp_ref->fm_refs[0].ref_col = c;
  1224.     }
  1225.   else
  1226.     {
  1227.       if (fm_tmp_ref_alloc <= from->refs_used)
  1228.     {
  1229.       fm_tmp_ref =
  1230.         ck_realloc (fm_tmp_ref, sizeof (struct ref_fm)
  1231.             + from->refs_used * sizeof (struct ref_array)) ;
  1232.       fm_tmp_ref_alloc = from->refs_used + 1;
  1233.     }
  1234.       fm_tmp_ref->refs_used = from->refs_used + 1;
  1235.       n = 0;
  1236.       while (n < from->refs_used
  1237.          && (from->fm_refs[n].ref_row < r
  1238.        || (from->fm_refs[n].ref_row == r && from->fm_refs[n].ref_col <= c)))
  1239.     {
  1240.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n];
  1241.       n++;
  1242.     }
  1243.       fm_tmp_ref->fm_refs[n].ref_row = r;
  1244.       fm_tmp_ref->fm_refs[n].ref_col = c;
  1245.       while (n < from->refs_used)
  1246.     {
  1247.       fm_tmp_ref->fm_refs[n + 1] = from->fm_refs[n];
  1248.       n++;
  1249.     }
  1250.     }
  1251.   *where = find_fm_ref ();
  1252.   if (from)
  1253.     flush_fm_ref (from);
  1254. }
  1255.  
  1256. #ifdef __STDC__
  1257. static void
  1258. flush_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1259. #else
  1260. static void
  1261. flush_ref_fm (where, r, c)
  1262.      struct ref_fm **where;
  1263.      CELLREF r;
  1264.      CELLREF c;
  1265. #endif
  1266. {
  1267.   struct ref_fm *from;
  1268.   int n;
  1269.  
  1270.   from = *where;
  1271. #ifdef TEST
  1272.   if (!from)
  1273.     {
  1274.       io_error_msg ("No refs in flush_ref_fm(%p,%u,%u)", where, r, c);
  1275.       return;
  1276.     }
  1277. #endif
  1278.   if (!from)
  1279.     return;
  1280.   if (from->refs_used == 1)
  1281.     {
  1282.       *where = 0;
  1283.       flush_fm_ref (from);
  1284.       return;
  1285.     }
  1286.   fm_tmp_ref->refs_used = from->refs_used - 1;
  1287.   n = 0;
  1288.   while (n < from->refs_used
  1289.      && (from->fm_refs[n].ref_row < r
  1290.     || (from->fm_refs[n].ref_row == r && from->fm_refs[n].ref_col < c)))
  1291.     {
  1292.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n];
  1293.       n++;
  1294.     }
  1295. #ifdef TEST
  1296.   if (n == from->refs_used)
  1297.     {
  1298.       io_error_msg ("No refs from %u,%u in %p in flush_refs_fm", r, c, where);
  1299.       return;
  1300.     }
  1301. #endif
  1302.   while (n < fm_tmp_ref->refs_used)
  1303.     {
  1304.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n + 1];
  1305.       n++;
  1306.     }
  1307.   *where = find_fm_ref ();
  1308.   flush_fm_ref (from);
  1309. }
  1310.  
  1311. #ifdef TEST
  1312.  
  1313. void
  1314. dbg_print_ref_fm (rf)
  1315.      struct ref_fm *rf;
  1316. {
  1317.   int nr;
  1318.   char *bufp;
  1319.  
  1320.   if (rf)
  1321.     {
  1322.       io_text_line ("fm %p: refcnt %u  next %p  used %u",
  1323.             rf, rf->refs_refcnt, rf->refs_next, rf->refs_used);
  1324.       for (nr = 0, bufp = print_buf; nr < rf->refs_used; nr++)
  1325.     {
  1326.       (void) sprintf (bufp, " %s", cell_name (rf->fm_refs[nr].ref_row, rf->fm_refs[nr].ref_col));
  1327.       if (nr % 10 == 9)
  1328.         {
  1329.           io_text_line (print_buf);
  1330.           bufp = print_buf;
  1331.         }
  1332.       else
  1333.         bufp += strlen (bufp);
  1334.     }
  1335.       if (nr % 10)
  1336.     io_text_line (print_buf);
  1337.     }
  1338. }
  1339.  
  1340. #endif
  1341.  
  1342. #ifdef __STDC__
  1343. static struct ref_to *
  1344. find_to_ref (void)
  1345. #else
  1346. static struct ref_to *
  1347. find_to_ref ()
  1348. #endif
  1349. {
  1350.   struct ref_to *tmp;
  1351.   int n;
  1352.   unsigned long hash;
  1353.  
  1354.   /* io_error_msg("find_to_ref %u %u",to_tmp_ref->refs_used,to_tmp_ref->to_refs[0]); */
  1355. #if 1
  1356.   for (hash = 0, n = 0; n < to_tmp_ref->refs_used; n++)
  1357.     hash += (n + 1) * to_tmp_ref->to_refs[n];
  1358.  
  1359.   hash %= TO_HASH_NUM;
  1360. #else
  1361.   hash = to_tmp_ref->refs_used;
  1362. #endif
  1363.   for (tmp = to_list[hash]; tmp; tmp = tmp->refs_next)
  1364.     {
  1365.       /* io_error_msg("%p(%u)->%p  %u %u",tmp,tmp->refs_refcnt,
  1366.             tmp->refs_next,tmp->refs_used,tmp->to_refs[0]); */
  1367.       if (tmp->refs_used != to_tmp_ref->refs_used)
  1368.     continue;
  1369.       if (!bcmp (tmp->to_refs, to_tmp_ref->to_refs, to_tmp_ref->refs_used))
  1370.     {
  1371.       /* io_error_msg("Hit!"); */
  1372.       tmp->refs_refcnt++;
  1373.       return tmp;
  1374.     }
  1375. #ifdef TEST
  1376.       else
  1377.     to_misses++;
  1378. #endif
  1379.     }
  1380.  
  1381.   /* io_error_msg("Miss. .."); */
  1382.   tmp = ck_malloc (sizeof (struct ref_to) + to_tmp_ref->refs_used - 1);
  1383.   tmp->refs_next = to_list[hash];
  1384.   to_list[hash] = tmp;
  1385.   tmp->refs_refcnt = 1;
  1386.   tmp->refs_used = to_tmp_ref->refs_used;
  1387.   bcopy (to_tmp_ref->to_refs, tmp->to_refs, tmp->refs_used);
  1388.  
  1389.   return tmp;
  1390. }
  1391.  
  1392. #ifdef __STDC__
  1393. void
  1394. add_ref_to (int whereto)
  1395. #else
  1396. void
  1397. add_ref_to (whereto)
  1398.      int whereto;
  1399. #endif
  1400. {
  1401.   struct ref_to *from;
  1402.   int n;
  1403.  
  1404.   from = my_cell->cell_refs_to;
  1405.   if (!from)
  1406.     {
  1407.       if (!to_tmp_ref)
  1408.     {
  1409.       to_tmp_ref = ck_malloc (sizeof (struct ref_to));
  1410.       to_tmp_ref_alloc = 1;
  1411.     }
  1412.       to_tmp_ref->refs_used = 1;
  1413.       to_tmp_ref->to_refs[0] = whereto;
  1414.     }
  1415.   else
  1416.     {
  1417.       if (to_tmp_ref_alloc <= from->refs_used)
  1418.     {
  1419.       to_tmp_ref = ck_realloc (to_tmp_ref, sizeof (struct ref_to) + from->refs_used);
  1420.       to_tmp_ref_alloc = from->refs_used + 1;
  1421.     }
  1422.       to_tmp_ref->refs_used = from->refs_used + 1;
  1423.       n = 0;
  1424.       while (n < from->refs_used && from->to_refs[n] < whereto)
  1425.     {
  1426.       to_tmp_ref->to_refs[n] = from->to_refs[n];
  1427.       n++;
  1428.     }
  1429.       to_tmp_ref->to_refs[n] = whereto;
  1430.       while (n < from->refs_used)
  1431.     {
  1432.       to_tmp_ref->to_refs[n + 1] = from->to_refs[n];
  1433.       n++;
  1434.     }
  1435.       flush_ref_to (&(my_cell->cell_refs_to));
  1436.     }
  1437.   my_cell->cell_refs_to = find_to_ref ();
  1438. }
  1439.  
  1440. #ifdef __STDC__
  1441. static void
  1442. flush_ref_to (struct ref_to **where)
  1443. #else
  1444. static void
  1445. flush_ref_to (where)
  1446.      struct ref_to **where;
  1447. #endif
  1448. {
  1449.   struct ref_to *tmp;
  1450.   struct ref_to *old;
  1451.   int n;
  1452.   unsigned long hash;
  1453.  
  1454. #ifdef TEST
  1455.   if (!where || !*where)
  1456.     {
  1457.       io_error_msg ("null flush_ref_to(%p)", where);
  1458.       return;
  1459.     }
  1460. #endif
  1461.   old = *where;
  1462.   *where = 0;
  1463.   --(old->refs_refcnt);
  1464.  
  1465. #ifdef DEFER_FREE
  1466.   return;
  1467. #endif
  1468.   if (!old->refs_refcnt)
  1469.     {
  1470. #if 1
  1471.       for (hash = 0, n = 0; n < old->refs_used; n++)
  1472.     hash += (n + 1) * old->to_refs[n];
  1473.  
  1474.       hash %= TO_HASH_NUM;
  1475. #else
  1476.       hash = old->refs_used;
  1477. #endif
  1478.       if (to_list[hash] == old)
  1479.     to_list[hash] = old->refs_next;
  1480.       else
  1481.     {
  1482.       for (tmp = to_list[hash]; tmp && tmp->refs_next != old; tmp = tmp->refs_next)
  1483.         ;
  1484. #ifdef TEST
  1485.       if (!tmp)
  1486.         {
  1487.           io_error_msg ("Old not in refs_list in flush_to_ref(%p)", old);
  1488.           return;
  1489.         }
  1490. #endif
  1491.       tmp->refs_next = old->refs_next;
  1492.     }
  1493.       free (old);
  1494.     }
  1495. }
  1496.  
  1497. #ifdef TEST
  1498. void
  1499. dbg_print_ref_to (rt, form)
  1500.      struct ref_to *rt;
  1501.      unsigned char *form;
  1502. {
  1503.   int nr;
  1504.   char *bufp;
  1505.  
  1506.   if (rt)
  1507.     {
  1508.       io_text_line ("to %p: refcnt %u  next %p  used %u",
  1509.             rt, rt->refs_refcnt, rt->refs_next, rt->refs_used);
  1510.       for (nr = 0, bufp = print_buf; nr < rt->refs_used; nr++)
  1511.     {
  1512.       (void) sprintf (bufp, " %3d (%#4x)", rt->to_refs[nr], form[rt->to_refs[nr]]);
  1513.       if (nr % 7 == 6)
  1514.         {
  1515.           io_text_line (print_buf);
  1516.           bufp = print_buf;
  1517.         }
  1518.       else
  1519.         bufp += strlen (bufp);
  1520.     }
  1521.       if (nr % 7)
  1522.     io_text_line (print_buf);
  1523.     }
  1524. }
  1525.  
  1526. void
  1527. ref_stats ()
  1528. {
  1529.   int n;
  1530.   int cur;
  1531.   struct ref_fm *rf;
  1532.   struct ref_to *rt;
  1533.  
  1534.   int rf_max = 0;
  1535.   int rf_num = 0;
  1536.   int rf_shared = 0;
  1537.   int rf_saved = 0;
  1538.   int rf_zero = 0;
  1539.  
  1540.   int rt_max = 0;
  1541.   int rt_num = 0;
  1542.   int rt_shared = 0;
  1543.   int rt_saved = 0;
  1544.   int rt_zero = 0;
  1545.  
  1546.   for (n = 0; n < FM_HASH_NUM; n++)
  1547.     {
  1548.       cur = 0;
  1549.       for (rf = fm_list[n]; rf; rf = rf->refs_next)
  1550.     {
  1551.       if (rf->refs_refcnt == 0)
  1552.         rf_zero++;
  1553.       if (rf->refs_refcnt > 1)
  1554.         {
  1555.           rf_shared++;
  1556.           rf_saved += rf->refs_refcnt - 1;
  1557.         }
  1558.       rf_num++;
  1559.       cur++;
  1560.     }
  1561.       if (cur > rf_max)
  1562.     rf_max = cur;
  1563.     }
  1564.   for (n = 0; n < TO_HASH_NUM; n++)
  1565.     {
  1566.       cur = 0;
  1567.       for (rt = to_list[n]; rt; rt = rt->refs_next)
  1568.     {
  1569.       if (rt->refs_refcnt == 0)
  1570.         rt_zero++;
  1571.       if (rt->refs_refcnt > 1)
  1572.         {
  1573.           rt_shared++;
  1574.           rt_saved += rt->refs_refcnt - 1;
  1575.         }
  1576.       rt_num++;
  1577.       cur++;
  1578.     }
  1579.       if (cur > rt_max)
  1580.     rt_max = cur;
  1581.     }
  1582.   io_text_line ("from: %d refs, max_length %d, shared %d, saved %d, zero_ref %d, missed %d\n", rf_num, rf_max, rf_shared, rf_saved, rf_zero, fm_misses);
  1583.   io_text_line ("to: %d refs, max_length %d, shared %d, saved %d, zero_ref %d, missed %d\n", rt_num, rt_max, rt_shared, rt_saved, rt_zero, to_misses);
  1584. }
  1585.  
  1586. #endif
  1587. #else
  1588.  
  1589. #ifdef __STDC__
  1590. static void
  1591. add_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1592. #else
  1593. static void
  1594. add_ref_fm (where, r, c)
  1595.      struct ref_fm **where;
  1596.      CELLREF r;
  1597.      CELLREF c;
  1598. #endif
  1599. {
  1600.   struct ref_fm *ref;
  1601.  
  1602.   ref = *where;
  1603.   if (!ref)
  1604.     {
  1605.       *where = ref = ck_malloc (sizeof (struct ref_fm) + (REF_START - 1) * sizeof (struct ref_array));
  1606.       ref->refs_alloc = REF_START;
  1607.       ref->refs_used = 0;
  1608.     }
  1609.   else if (ref->refs_alloc == ref->refs_used)
  1610.     {
  1611.       ref->refs_alloc REF_INC;
  1612.       *where = ref = ck_realloc (ref, sizeof (struct ref_fm) + (ref->refs_alloc - 1) * sizeof (struct ref_array));
  1613.     }
  1614.   ref->fm_refs[ref->refs_used].ref_row = r;
  1615.   ref->fm_refs[ref->refs_used].ref_col = c;
  1616.   ref->refs_used++;
  1617. }
  1618.  
  1619. #ifdef __STDC__
  1620. static void
  1621. flush_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1622. #else
  1623. static void
  1624. flush_ref_fm (where, r, c)
  1625.      struct ref_fm **where;
  1626.      CELLREF r;
  1627.      CELLREF c;
  1628. #endif
  1629. {
  1630.   int n;
  1631.   struct ref_fm *ref;
  1632.  
  1633.   ref = *where;
  1634. #ifdef TEST
  1635.   if (!ref)
  1636.     {
  1637.       io_error_msg ("%s->No refs in flush_ref_fm(%d,%d)", cell_name (cur_row, cur_col), r, c);
  1638.       return;
  1639.     }
  1640. #endif
  1641.   for (n = 0; n < ref->refs_used; n++)
  1642.     if (ref->fm_refs[n].ref_row == r && ref->fm_refs[n].ref_col == c)
  1643.       {
  1644.     ref->fm_refs[n] = ref->fm_refs[ref->refs_used - 1];
  1645.     --(ref->refs_used);
  1646.     return;
  1647.       }
  1648. #ifdef TEST
  1649.   io_error_msg ("%s->Can't flush_ref_fm(%d,%d)", cell_name (cur_row, cur_col), r, c);
  1650.   return;
  1651. #endif
  1652. }
  1653.  
  1654. #ifdef __STDC__
  1655. void
  1656. add_ref_to (int whereto)
  1657. #else
  1658. void
  1659. add_ref_to (whereto)
  1660.      int whereto;
  1661. #endif
  1662. {
  1663.   struct ref_to *ref;
  1664.  
  1665.   ref = my_cell->cell_refs_to;
  1666.   if (!ref)
  1667.     {
  1668.       my_cell->cell_refs_to = ref = ck_malloc (sizeof (struct ref_to) + (REF_START - 1) * sizeof (unsigned char));
  1669.       ref->refs_alloc = REF_START;
  1670.       ref->refs_used = 0;
  1671.     }
  1672.   else if (ref->refs_alloc == ref->refs_used)
  1673.     {
  1674.       ref->refs_alloc REF_INC;
  1675.       my_cell->cell_refs_to = ref = ck_realloc (ref, sizeof (struct ref_to) +
  1676.                 (ref->refs_alloc - 1) * sizeof (unsigned char));
  1677.     }
  1678.   ref->to_refs[ref->refs_used] = whereto;
  1679.   ref->refs_used++;
  1680. }
  1681.  
  1682. #ifdef TEST
  1683.  
  1684. void
  1685. dbg_print_ref_fm (rf)
  1686.      struct ref_fm *rf;
  1687. {
  1688.   int nr;
  1689.   char *bufp;
  1690.  
  1691.   if (rf)
  1692.     {
  1693.       io_text_line ("fm %p: alloc %u  used %u",
  1694.             rf, rf->refs_alloc, rf->refs_used);
  1695.       for (nr = 0, bufp = print_buf; nr < rf->refs_used; nr++)
  1696.     {
  1697.       (void) sprintf (bufp, " %s", cell_name (rf->fm_refs[nr].ref_row, rf->fm_refs[nr].ref_col));
  1698.       if (nr % 10 == 9)
  1699.         {
  1700.           io_text_line (print_buf);
  1701.           bufp = print_buf;
  1702.         }
  1703.       else
  1704.         bufp += strlen (bufp);
  1705.     }
  1706.       if (nr % 10)
  1707.     io_text_line (print_buf);
  1708.     }
  1709. }
  1710.  
  1711. void
  1712. dbg_print_ref_to (rt, form)
  1713.      struct ref_to *rt;
  1714.      unsigned char *form;
  1715. {
  1716.   int nr;
  1717.   char *bufp;
  1718.  
  1719.   if (rt)
  1720.     {
  1721.       io_text_line ("to %p:  alloc %u  used %u",
  1722.             rt, rt->refs_alloc, rt->refs_used);
  1723.       for (nr = 0, bufp = print_buf; nr < rt->refs_used; nr++)
  1724.     {
  1725.       (void) sprintf (bufp, " %3d (%#4x)", rt->to_refs[nr], form[rt->to_refs[nr]]);
  1726.       if (nr % 7 == 6)
  1727.         {
  1728.           io_text_line (print_buf);
  1729.           bufp = print_buf;
  1730.         }
  1731.       else
  1732.         bufp += strlen (bufp);
  1733.     }
  1734.       if (nr % 7)
  1735.     io_text_line (print_buf);
  1736.     }
  1737. }
  1738.  
  1739. void
  1740. ref_stats ()
  1741. {
  1742.   CELL *cp;
  1743.  
  1744.   int rf_num = 0;
  1745.   int rf_zero = 0;
  1746.   int rf_biggest = 0;
  1747.  
  1748.   int rt_num = 0;
  1749.   int rt_zero = 0;
  1750.   int rt_biggest = 0;
  1751.  
  1752.   find_cells_in_range (&all_rng);
  1753.   while (cp = next_cell_in_range ())
  1754.     {
  1755.       if (cp->cell_refs_from)
  1756.     {
  1757.       if (cp->cell_refs_from->refs_used > rf_biggest)
  1758.         rf_biggest = cp->cell_refs_from->refs_used;
  1759.       if (cp->cell_refs_from->refs_used == 0)
  1760.         rf_zero++;
  1761.       rf_num++;
  1762.     }
  1763.       if (cp->cell_refs_to)
  1764.     {
  1765.       if (cp->cell_refs_to->refs_used > rt_biggest)
  1766.         rt_biggest = cp->cell_refs_to->refs_used;
  1767.       if (cp->cell_refs_to->refs_used == 0)
  1768.         rt_zero++;
  1769.       rt_num++;
  1770.     }
  1771.     }
  1772.   io_text_line ("from: %d refs, biggest %d, zero_ref %d\n", rf_num, rf_biggest, rf_zero);
  1773.   io_text_line ("to: %d refs, biggest %d,zero_ref %d\n", rt_num, rt_biggest, rt_zero);
  1774. }
  1775.  
  1776. #endif
  1777.  
  1778. #endif
  1779.  
  1780. /* ------------- Routines for dealing with moving cells -------------------- */
  1781.  
  1782. static struct rng *shift_fm;
  1783. static int shift_ov;
  1784. static int shift_dn;
  1785.  
  1786. /* This removes all the CELL_REF_FM links associated with a 
  1787.  * variable, and adjusts the variables value.
  1788.  * After calling this function, one must also call 
  1789.  * finish_shift_var to install the new CELL_REF_FM links.
  1790.  */
  1791. #ifdef __STDC__
  1792. static void 
  1793. start_shift_var (char *name, struct var *v)
  1794. #else
  1795. static void 
  1796. start_shift_var (name, v)
  1797.      char *name;
  1798.      struct var *v;
  1799. #endif
  1800. {
  1801.   int n;
  1802.   int nn;
  1803.  
  1804.  
  1805.   n = (BETWEEN (v->v_rng.hc, shift_fm->lc, shift_fm->hc) << 3)
  1806.     + (BETWEEN (v->v_rng.lc, shift_fm->lc, shift_fm->hc) << 2)
  1807.     + (BETWEEN (v->v_rng.hr, shift_fm->lr, shift_fm->hr) << 1)
  1808.     + BETWEEN (v->v_rng.lr, shift_fm->lr, shift_fm->hr);
  1809.   switch (n)
  1810.     {
  1811.     case 0:
  1812.     case 1:
  1813.     case 2:
  1814.     case 3:
  1815.     case 4:
  1816.     case 8:
  1817.     case 12:
  1818.       /* Null intersection, ignore it */
  1819.       break;
  1820.  
  1821.     case 5:            /* The bottom and right */
  1822.     case 6:            /* The bottom and left */
  1823.     case 9:            /* The top and right */
  1824.     case 10:            /* The top and left */
  1825.       /* The var sticks out of the range we're moving */
  1826.       /* on two sides.  what should we do? */
  1827.       io_error_msg ("'%s' can't be adjusted", v->var_name);
  1828.       break;
  1829.  
  1830.     case 7:            /* v->hc sticks out the right */
  1831.     case 11:            /* v->lc sticks out the left */
  1832.     case 13:            /* v->hr sticks out the bottom */
  1833.     case 14:            /* v->lr sticks out the top */
  1834.       /* It only sticks out on one side.  We can
  1835.            (try to) adjust it */
  1836.  
  1837.     case 15:            /* var is completely inside the range */
  1838.       if (v->var_ref_fm)
  1839.     {
  1840.       for (nn = 0; nn < v->var_ref_fm->refs_used; nn++)
  1841.         {
  1842.           flush_range_ref (&(v->v_rng),
  1843.                    v->var_ref_fm->fm_refs[nn].ref_row,
  1844.                    v->var_ref_fm->fm_refs[nn].ref_col);
  1845.         }
  1846.     }
  1847.       if (n != 7)
  1848.     v->v_rng.hc += shift_ov;
  1849.       if (n != 11)
  1850.     v->v_rng.lc += shift_ov;
  1851.       if (n != 13)
  1852.     v->v_rng.hr += shift_dn;
  1853.       if (n != 14)
  1854.     v->v_rng.lr += shift_dn;
  1855.       v->var_flags = VAR_DANGLING_RANGE;
  1856.     }
  1857. }
  1858.  
  1859.  
  1860. #ifdef __STDC__
  1861. static void 
  1862. finish_shift_var (char *name, struct var *v)
  1863. #else
  1864. static void 
  1865. finish_shift_var (name, v)
  1866.      char *name;
  1867.      struct var *v;
  1868. #endif
  1869. {
  1870.   int n;
  1871.   if (!v->var_ref_fm || v->var_flags != VAR_DANGLING_RANGE)
  1872.     return;
  1873.  
  1874.   v->var_flags = VAR_RANGE;
  1875.  
  1876.   for (n = 0; n < v->var_ref_fm->refs_used; n++)
  1877.     {
  1878.       cur_row = v->var_ref_fm->fm_refs[n].ref_row;
  1879.       cur_col = v->var_ref_fm->fm_refs[n].ref_col;
  1880.       add_range_ref (&(v->v_rng));
  1881.     }
  1882. }
  1883.  
  1884. #define RIGHT    8
  1885. #define LEFT    4
  1886. #define BOTTOM    2
  1887. #define TOP    1
  1888.  
  1889. /*
  1890.  * This iterates over the region FM, preparing the cells there to be shifted
  1891.  * OV(er) and D(ow)N.
  1892.  *
  1893.  * After this, the ref_fm and ref_to lists of a cell within the region should
  1894.  * be appropriate to the location that cell will be shifted to.
  1895.  * 
  1896.  * Variables and references to variables are also shifted.
  1897.  */
  1898. #ifdef __STDC__
  1899. void
  1900. shift_outside (struct rng *fm, int dn, int ov)
  1901. #else
  1902. void
  1903. shift_outside (fm, dn, ov)
  1904.      struct rng *fm;
  1905.      int dn;
  1906.      int ov;
  1907. #endif
  1908. {
  1909.   CELL *cp;
  1910.   CELL *fcp;
  1911.   CELL *tcp;
  1912.   int n;
  1913.   int fn;
  1914.   CELLREF rr, cc;
  1915.   CELLREF frr, fcc;
  1916.   CELLREF trr, tcc;
  1917.   unsigned char *ffp;
  1918.   unsigned char *fp;
  1919.   struct rng orng;
  1920.  
  1921.   char *ptr;
  1922.   unsigned long val;
  1923.   static char DEF_REF[] = "DEFREF";
  1924.   static char DEF_RNG[] = "DEFRNG";
  1925.  
  1926.   /* Variables and references to variables are also shifted. */
  1927.   shift_fm = fm;
  1928.   shift_dn = dn;
  1929.   shift_ov = ov;
  1930.   for_all_vars (start_shift_var);
  1931.  
  1932.   /* This stack is used to defer adjustments to references that are entirely 
  1933.    * within FM.  Intra-FM references are adjusted after references into and
  1934.    * out of FM.
  1935.    */
  1936.  
  1937.   if (!moving)
  1938.     moving = init_stack ();
  1939.  
  1940.   find_cells_in_range (fm);
  1941.  
  1942.   while (cp = next_row_col_in_range (&rr, &cc))
  1943.     {
  1944.       /* cp/rr/cc is a cell in FM. */
  1945.  
  1946.       /* First, adjust references FROM the region */
  1947.       if (cp->cell_refs_to)
  1948.     {
  1949.       for (n = 0; n < cp->cell_refs_to->refs_used; n++)
  1950.         {
  1951.           fp = &(cp->cell_formula[cp->cell_refs_to->to_refs[n]]);
  1952.           switch (*fp)
  1953.         {
  1954.         case R_CELL:
  1955.         case R_CELL | ROWREL:
  1956.         case R_CELL | COLREL:
  1957.         case R_CELL | ROWREL | COLREL:
  1958.           /* Trr/cc/cp is the cell being referenced */
  1959.           trr = GET_ROW (fp + 1);
  1960.           tcc = GET_COL (fp + 1);
  1961.           tcp = find_cell (trr, tcc);
  1962.  
  1963.           /* Get rid of the backpointer to this reference. */
  1964.           flush_ref_fm (&(tcp->cell_refs_from), rr, cc);
  1965.  
  1966.           /* frr/fcc is the new address of the referenced cell.
  1967.            * The address will change if Trr/cc happens to be 
  1968.               * in the region that is moving, or if the reference
  1969.            * is a relative reference.
  1970.            */
  1971.           fn = (BETWEEN (trr, fm->lr, fm->hr)
  1972.             && BETWEEN (tcc, fm->lc, fm->hc)); 
  1973.           frr = (fn || (((*fp) & ROWREL))) ? trr + dn : trr;
  1974.           fcc = (fn || (((*fp) & COLREL))) ? tcc + ov : tcc;
  1975.  
  1976.           PUT_ROW (fp + 1, frr); /* Adjust the formula byte-code. */
  1977.           PUT_COL (fp + 1, fcc); /* This might even be a noop. */
  1978.  
  1979.           /* Reinstall the backreference, unless the new address of the
  1980.            * referenced cell is w/in the region being moved. (In which
  1981.            * case, defer making the backreference).
  1982.            */
  1983.           if (BETWEEN(frr, fm->lr, fm->hr) && BETWEEN(fcc, fm->lc, fm->hc))
  1984.             {
  1985.               push_stack (moving, (VOIDSTAR) TO_MAGIC (rr + dn, cc + ov));
  1986.               push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  1987.               push_stack (moving, DEF_REF);
  1988.             }
  1989.           else
  1990.             {
  1991.               tcp = find_or_make_cell (frr, fcc);
  1992.               add_ref_fm (&(tcp->cell_refs_from), rr + dn, cc + ov);
  1993.               cp = find_cell (rr, cc);
  1994.             }
  1995.  
  1996.           break;
  1997.  
  1998.         case VAR:
  1999.           {
  2000.             struct var * varp;
  2001.             bcopy ((VOIDSTAR) (fp + 1),
  2002.                (VOIDSTAR)&varp, sizeof (struct var *));
  2003.             flush_ref_fm (&varp->var_ref_fm, rr, cc);
  2004.             add_ref_fm (&varp->var_ref_fm, rr + dn, cc + ov);
  2005.             break;
  2006.           }
  2007.  
  2008.         case RANGE:
  2009.         case RANGE | LRREL:
  2010.         case RANGE | HRREL:
  2011.         case RANGE | LCREL:
  2012.         case RANGE | HCREL:
  2013.         case RANGE | LRREL | HRREL:
  2014.         case RANGE | LRREL | LCREL:
  2015.         case RANGE | LRREL | HCREL:
  2016.         case RANGE | HRREL | LCREL:
  2017.         case RANGE | HRREL | HCREL:
  2018.         case RANGE | LCREL | HCREL:
  2019.         case RANGE | LRREL | LCREL | HCREL:
  2020.         case RANGE | LRREL | HRREL | LCREL:
  2021.         case RANGE | LRREL | HRREL | HCREL:
  2022.         case RANGE | HRREL | LCREL | HCREL:
  2023.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  2024.           /* orng is the range being referenced. */
  2025.           GET_RNG (fp + 1, &orng);
  2026.  
  2027.           /* Get rid of backpointers to this reference. */
  2028.           flush_range_ref (&orng, rr, cc);
  2029.  
  2030.                   /* This asks -- does the referenced region
  2031.                       * intersect the region being moved at the: 
  2032.                    */
  2033.           fn = ((BETWEEN (orng.hc, fm->lc, fm->hc) << 3)   /* right?  8 */
  2034.                | (BETWEEN (orng.lc, fm->lc, fm->hc) << 2)  /* left?   4 */
  2035.                | (BETWEEN (orng.hr, fm->lr, fm->hr) << 1)  /* bottom? 2 */
  2036.                | BETWEEN (orng.lr, fm->lr, fm->hr));       /* top?    1 */
  2037.  
  2038.           /* In this switch, a union of masks represents a conjunction 
  2039.            * of intersections.  So, LEFT | TOP means `interects at left
  2040.            * and top'. 
  2041.            */
  2042.           switch (fn)
  2043.             {
  2044.               /* Most of the time, the referenced region is moved only
  2045.                * if the reference is relative.
  2046.                    */
  2047.             case LEFT | TOP:
  2048.             case LEFT | BOTTOM:
  2049.             case RIGHT | TOP:
  2050.             case RIGHT | BOTTOM:
  2051.  
  2052.               /* There used to be a warning given to the user here, but
  2053.                * that seems silly, no? 
  2054.                */
  2055.  
  2056.             case 0:
  2057.             case TOP:
  2058.             case BOTTOM:
  2059.             case TOP | BOTTOM:
  2060.             case LEFT:
  2061.             case RIGHT:
  2062.             case LEFT | RIGHT:
  2063.               if ((*fp) & LRREL)
  2064.             orng.lr += dn;
  2065.               if ((*fp) & HRREL)
  2066.             orng.hr += dn;
  2067.               if ((*fp) & LCREL)
  2068.             orng.lc += ov;
  2069.               if ((*fp) & HCREL)
  2070.             orng.hc += ov;
  2071.               break;
  2072.  
  2073.               /* If the referenced range contains rows or columns that
  2074.                * are entirely within the region being moved, then 
  2075.                * the region is moved, shrunk or stretched.
  2076.                */
  2077.             case LEFT | BOTTOM | TOP:
  2078.             case RIGHT | BOTTOM | TOP:
  2079.             case RIGHT | LEFT | TOP:
  2080.             case RIGHT | LEFT | BOTTOM:
  2081.             case RIGHT | LEFT | BOTTOM | TOP:
  2082.               if (fn != (LEFT | BOTTOM | TOP))
  2083.             orng.hc += ov;
  2084.               if (fn != (RIGHT | BOTTOM | TOP))
  2085.             orng.lc += ov;
  2086.               if (fn != (RIGHT | LEFT | TOP))
  2087.             orng.hr += dn;
  2088.               if (fn != (RIGHT | LEFT | BOTTOM))
  2089.             orng.lr += dn;
  2090.               break;
  2091.             }
  2092.           PUT_RNG (fp + 1, &orng); /* Patch the bytecode. */
  2093.  
  2094.           push_stack (moving, (VOIDSTAR) fp);
  2095.           push_stack (moving, (VOIDSTAR) TO_MAGIC (rr + dn, cc + ov));
  2096.           push_stack (moving, DEF_RNG);
  2097.           break;
  2098.  
  2099.         default:
  2100.           {
  2101.             struct function *fun;
  2102.  
  2103.             if (*fp < USR1)
  2104.               fun = &the_funs[*fp];
  2105.             else
  2106.               fun = &usr_funs[*fp - USR1][fp[1]];
  2107.  
  2108.             if (fun->fn_comptype & C_T)
  2109.               {
  2110.             flush_ref_fm (&timer_cells, rr, cc);
  2111.             add_ref_fm (&timer_cells, rr + dn, cc + ov);
  2112.               }
  2113.           }
  2114.           break;
  2115.         }
  2116.  
  2117.         }
  2118.     }
  2119.  
  2120.       /* Next, adjust references TO the region */
  2121.       for (n = 0; cp->cell_refs_from && n < cp->cell_refs_from->refs_used; n++)
  2122.     {
  2123.       /* The second enclosed loop over the bytecode will fix all of the
  2124.        * references to this cell.  This loop is here because a 
  2125.        * refs_fm structure may contain more than one occurence of the
  2126.        * referencing cell.  We don't want to adjust the same bytecode
  2127.        * twice.
  2128.        */
  2129.       while ((n < cp->cell_refs_from->refs_used - 1)
  2130.          && (cp->cell_refs_from->fm_refs[n].ref_row == 
  2131.              cp->cell_refs_from->fm_refs[n + 1].ref_row)
  2132.          && (cp->cell_refs_from->fm_refs[n].ref_col == 
  2133.              cp->cell_refs_from->fm_refs[n + 1].ref_col))
  2134.         ++n;
  2135.  
  2136.       /* For each cell that referenced this one, look
  2137.        * at the type of reference involved
  2138.        */
  2139.       frr = cp->cell_refs_from->fm_refs[n].ref_row;
  2140.       fcc = cp->cell_refs_from->fm_refs[n].ref_col;
  2141.  
  2142.       /* Unless the reference is from inside the region we're moving, in 
  2143.        * which case, it has already been adjusted.
  2144.        * 
  2145.        * (This test seems unnecessary but harmless. -tl)
  2146.        */
  2147.       if (BETWEEN (frr, fm->lr, fm->hr) && BETWEEN (fcc, fm->lc, fm->hc))
  2148.         continue;
  2149.  
  2150.       /* Find the cell that references cp. */
  2151.       fcp = find_cell (frr, fcc);
  2152.  
  2153.       /* Search the byte-code for the reference. */
  2154.       for (fn = 0; fcp->cell_refs_to && fn < fcp->cell_refs_to->refs_used; fn++)
  2155.         {
  2156.  
  2157.           ffp = &(fcp->cell_formula[fcp->cell_refs_to->to_refs[fn]]);
  2158.           switch (*ffp)
  2159.         {
  2160.         case R_CELL:
  2161.         case R_CELL | ROWREL:
  2162.         case R_CELL | COLREL:
  2163.         case R_CELL | ROWREL | COLREL:
  2164.  
  2165.           trr = GET_ROW (ffp + 1);
  2166.           tcc = GET_COL (ffp + 1);
  2167.  
  2168.           if (trr != rr || tcc != cc)
  2169.             continue;
  2170.  
  2171.           {
  2172.             CELLREF old_tr = trr;
  2173.             CELLREF old_tc = tcc;
  2174.             /* Find the cell that fcp should reference now. */
  2175.             if (!((*ffp) & ROWREL))
  2176.               {
  2177.             trr += dn;
  2178.             PUT_ROW (ffp + 1, trr);
  2179.               }
  2180.             if (!((*ffp) & COLREL))
  2181.               {
  2182.             tcc += ov;
  2183.             PUT_COL (ffp + 1, tcc);
  2184.               }
  2185.             else
  2186.               /* If this is an abs reference, it doesn't change. */
  2187.               continue;
  2188.             /* Get rid of the now-invalid backpointer */
  2189.             {
  2190.               CELL * old_reffed = find_cell (old_tr, old_tc);
  2191.               flush_ref_fm (&(old_reffed->cell_refs_from), frr, fcc);
  2192.             }
  2193.           }
  2194.  
  2195.           if (BETWEEN (trr, fm->lr, fm->hr) && BETWEEN (tcc, fm->lc, fm->hc))
  2196.             {
  2197.               push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  2198.               push_stack (moving, (VOIDSTAR) TO_MAGIC (trr, tcc));
  2199.               push_stack (moving, DEF_REF);
  2200.             }
  2201.           else
  2202.             {
  2203.               cp = find_or_make_cell (trr, tcc);
  2204.               add_ref_fm (&(cp->cell_refs_from), frr, fcc);
  2205.             }    
  2206.  
  2207.  
  2208.         case VAR:
  2209.           /* This case is taken care of by {start,finish}_shift_vars */
  2210.           continue;
  2211.  
  2212.         case RANGE:
  2213.         case RANGE | LRREL:
  2214.         case RANGE | LRREL | LCREL:
  2215.         case RANGE | LRREL | LCREL | HCREL:
  2216.         case RANGE | LRREL | HCREL:
  2217.         case RANGE | LRREL | HRREL:
  2218.         case RANGE | LRREL | HRREL | LCREL:
  2219.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  2220.         case RANGE | LRREL | HRREL | HCREL:
  2221.         case RANGE | HRREL:
  2222.         case RANGE | HRREL | LCREL:
  2223.         case RANGE | HRREL | LCREL | HCREL:
  2224.         case RANGE | HRREL | HCREL:
  2225.         case RANGE | LCREL:
  2226.         case RANGE | LCREL | HCREL:
  2227.         case RANGE | HCREL:
  2228.           GET_RNG (ffp + 1, &orng);
  2229.  
  2230.           if (!BETWEEN (rr, orng.lr, orng.hr) || !BETWEEN (cc, orng.lc, orng.hc))
  2231.             break;
  2232.  
  2233.           val = ((BETWEEN (orng.hc, fm->lc, fm->hc) << 3) /* right */
  2234.              + (BETWEEN (orng.lc, fm->lc, fm->hc) << 2) /* left */
  2235.              + (BETWEEN (orng.hr, fm->lr, fm->hr) << 1) /* bottom */
  2236.              + BETWEEN (orng.lr, fm->lr, fm->hr)); /* top */
  2237.  
  2238.           /* If the reference is absolute, or relative only in directions
  2239.            * that aren't changing, there's nothing to do. 
  2240.            */
  2241.           if (!(*ffp == RANGE
  2242.             || (!dn && ((*ffp) | LRREL | HRREL) == (RANGE | LRREL | HRREL))
  2243.             || (!ov && ((*ffp) | LCREL | HCREL) == (RANGE | LCREL | HCREL))))
  2244.             continue;
  2245.  
  2246.           /* If it's a case we don't know how to adjust, there's
  2247.            * nothing to do.  If there is no overlap, there's nothing to
  2248.            * do.
  2249.            */
  2250.           if ((val != (LEFT | BOTTOM | TOP))
  2251.               && (val != (RIGHT | BOTTOM | TOP))
  2252.               && (val != (RIGHT | LEFT | TOP))
  2253.               && (val != (RIGHT | LEFT | BOTTOM))
  2254.               && (val != (RIGHT | LEFT | BOTTOM | TOP)))
  2255.             continue;
  2256.           
  2257.           flush_range_ref (&orng, frr, fcc);
  2258.  
  2259.           if (val != (RIGHT | LEFT | BOTTOM))
  2260.             orng.lr += dn;
  2261.           if (val != (RIGHT | LEFT | TOP))
  2262.             orng.hr += dn;
  2263.           if (val != (RIGHT | BOTTOM | TOP))
  2264.             orng.lc += ov;
  2265.           if (val != (LEFT | BOTTOM  | TOP))
  2266.             orng.hc += ov;
  2267.           PUT_RNG (ffp + 1, &orng);
  2268.           push_stack (moving, (VOIDSTAR) ffp);
  2269.           push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  2270.           push_stack (moving, DEF_RNG);
  2271.           continue;
  2272. #ifdef TEST
  2273.         default:
  2274.           { struct function *fun; if (*ffp < USR1) fun =
  2275.               &the_funs[*ffp]; else if (*ffp >= SKIP) fun = 0, panic
  2276.             ("SKIP? in shift_outside()"); else fun =
  2277.               &usr_funs[*ffp][ffp[1]];
  2278.             if ((fun->fn_comptype & C_T) == 0) io_error_msg
  2279.               ("Unknown byte (%d) for reference_to #%d %d",
  2280.                *ffp, fn, fcp->cell_refs_to->to_refs[fn]);
  2281.           }
  2282.           break; 
  2283. #endif
  2284.         }
  2285.         }
  2286.     }
  2287.     }
  2288.  
  2289.   while (ptr = pop_stack (moving))
  2290.     {
  2291.       if (ptr == DEF_REF)
  2292.     {
  2293.       val = (unsigned long) pop_stack (moving);
  2294.       trr = MAGIC_ROW (val);
  2295.       tcc = MAGIC_COL (val);
  2296.       val = (unsigned long) pop_stack (moving);
  2297.       cp = find_or_make_cell (trr, tcc);
  2298.       add_ref_fm (&(cp->cell_refs_from), MAGIC_ROW (val), MAGIC_COL (val));
  2299.     }
  2300.       else if (ptr == DEF_RNG)
  2301.     {
  2302.       val = (unsigned long) pop_stack (moving);
  2303.       cur_row = MAGIC_ROW (val);
  2304.       cur_col = MAGIC_COL (val);
  2305.       ffp = (unsigned char *) pop_stack (moving);
  2306.  
  2307.       GET_RNG (ffp + 1, &orng);
  2308.       add_range_ref (&orng);
  2309.       if (my_cell)
  2310.         panic ("shift_outside: my_cell lost.");
  2311.       /* If this panic occurs, the caller should be recomputing
  2312.        * my_cell after shift_outside returns (and this useful panic
  2313.        * will have to be removed or my_cell set temporarily to 0).
  2314.        */
  2315.     }
  2316. #ifdef TEST
  2317.       else
  2318.     panic ("Now what (%p)?", ptr);
  2319. #endif
  2320.     }
  2321.   for_all_vars (finish_shift_var);
  2322.   /* flush_stack(moving); */
  2323. }
  2324.  
  2325. /* The formula in cell my_cell has moved by DN down and OV over, adjust
  2326.    everything so it'll still work */
  2327. #ifdef __STDC__
  2328. void
  2329. shift_formula (int r, int c, int dn, int ov)
  2330. #else
  2331. void
  2332. shift_formula (r, c, dn, ov)
  2333.      int r;            /* Address of my_cell. */
  2334.      int c;
  2335.      int dn;
  2336.      int ov;
  2337. #endif
  2338. {
  2339.   int n;
  2340.   unsigned char *fp;
  2341.  
  2342.   for (n = 0; n < my_cell->cell_refs_to->refs_used; n++)
  2343.     {
  2344.       fp = &(my_cell->cell_formula[my_cell->cell_refs_to->to_refs[n]]);
  2345.       switch (*fp)
  2346.     {
  2347.     case F_ROW:
  2348.     case F_COL:
  2349.       push_cell (cur_row, cur_col);
  2350.       break;
  2351.  
  2352.     case R_CELL:
  2353.     case R_CELL | ROWREL:
  2354.     case R_CELL | COLREL:
  2355.     case R_CELL | ROWREL | COLREL:
  2356.       {
  2357.         CELLREF trr, tcc;
  2358.         CELL *tcp;
  2359.  
  2360.         /* These are more difficult */
  2361.         trr = GET_ROW (fp + 1);
  2362.         tcc = GET_COL (fp + 1);
  2363.         tcp = find_cell (trr, tcc);
  2364. #ifdef TEST
  2365.         if (!tcp)
  2366.           panic ("Can't find_cell(%s) in shift_formula", cell_name (trr, tcc));
  2367. #endif
  2368.         flush_ref_fm (&(tcp->cell_refs_from), cur_row - dn, cur_col - ov);
  2369.  
  2370.         if (((*fp) & ROWREL) && dn)
  2371.           {
  2372.         trr += dn;
  2373.         PUT_ROW (fp + 1, trr);
  2374.           }
  2375.         if (((*fp) & COLREL) && ov)
  2376.           {
  2377.         tcc += ov;
  2378.         PUT_COL (fp + 1, tcc);
  2379.           }
  2380.         tcp = find_or_make_cell (trr, tcc);
  2381.         add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  2382.       }
  2383.       break;
  2384.  
  2385.     case RANGE:
  2386.     case RANGE | LRREL:
  2387.     case RANGE | LRREL | LCREL:
  2388.     case RANGE | LRREL | LCREL | HCREL:
  2389.     case RANGE | LRREL | HCREL:
  2390.     case RANGE | LRREL | HRREL:
  2391.     case RANGE | LRREL | HRREL | LCREL:
  2392.     case RANGE | LRREL | HRREL | LCREL | HCREL:
  2393.     case RANGE | LRREL | HRREL | HCREL:
  2394.     case RANGE | HRREL:
  2395.     case RANGE | HRREL | LCREL:
  2396.     case RANGE | HRREL | LCREL | HCREL:
  2397.     case RANGE | HRREL | HCREL:
  2398.     case RANGE | LCREL:
  2399.     case RANGE | LCREL | HCREL:
  2400.     case RANGE | HCREL:
  2401.       {
  2402.         struct rng orng;
  2403.         GET_RNG (fp + 1, &orng);
  2404.  
  2405.         flush_range_ref (&orng, cur_row - dn, cur_col - ov);
  2406.  
  2407.         if ((*fp) & LRREL)
  2408.           orng.lr += dn;
  2409.         if ((*fp) & HRREL)
  2410.           orng.hr += dn;
  2411.         if ((*fp) & LCREL)
  2412.           orng.lc += ov;
  2413.         if ((*fp) & HCREL)
  2414.           orng.hc += ov;
  2415.         PUT_RNG (fp + 1, &orng);
  2416.         add_range_ref (&orng);
  2417.         /* sparse array bug fixed here */
  2418.         my_cell = find_cell (r, c);
  2419.       }
  2420.       break;
  2421.  
  2422.     case VAR:
  2423.       {
  2424.         struct var *v;
  2425.         struct cell *tcp;
  2426.  
  2427.         bcopy (&fp[1], &v, sizeof (struct var *));
  2428.         flush_ref_fm (&(v->var_ref_fm), cur_row - dn, cur_col - ov);
  2429.         add_ref_fm (&(v->var_ref_fm), cur_row, cur_col);
  2430.         switch (v->var_flags)
  2431.           {
  2432.           case VAR_UNDEF:
  2433.         break;
  2434.  
  2435.           case VAR_CELL:
  2436.         tcp = find_cell (v->v_rng.lr, v->v_rng.lc);
  2437. #ifdef TEST
  2438.         if (!tcp)
  2439.           panic ("Can't find_cell(%s) in shift_formula", cell_name (v->v_rng.lr, v->v_rng.lc));
  2440. #endif
  2441.         flush_ref_fm (&(tcp->cell_refs_from), cur_row - dn, cur_col - ov);
  2442.         add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  2443.         break;
  2444.  
  2445.           case VAR_RANGE:
  2446.         flush_range_ref (&(v->v_rng), cur_row - dn, cur_col - ov);
  2447.         add_range_ref (&(v->v_rng));
  2448.         /* sparse array bug fixed here */
  2449.         my_cell = find_cell (r, c);
  2450.         break;
  2451.  
  2452. #ifdef TEST
  2453.           default:
  2454.         panic ("Unknown var type %d", v->var_flags);
  2455. #endif
  2456.           }
  2457.       }
  2458.       break;
  2459.  
  2460.     default:
  2461.       {
  2462.         struct function *fun;
  2463.  
  2464.         if (*fp < USR1)
  2465.           fun = &the_funs[*fp];
  2466. #ifdef TEST
  2467.         else if (*fp >= SKIP)
  2468.           fun = 0, panic ("SKIP? in shift_formula?");
  2469. #endif
  2470.         else
  2471.           fun = &usr_funs[*fp][fp[1]];
  2472.         /* These are easy */
  2473.         if (fun->fn_comptype & C_T)
  2474.           {
  2475.         flush_ref_fm (&timer_cells, cur_row - dn, cur_col - ov);
  2476.         add_ref_fm (&timer_cells, cur_row, cur_col);
  2477.           }
  2478. #ifdef TEST
  2479.         else
  2480.           panic ("How do I deal with byte %d in shift_formula()?", *fp);
  2481. #endif
  2482.       }
  2483.       break;
  2484.     }
  2485.     }
  2486. }
  2487.  
  2488.  
  2489. /* ---------------- Routines for dealing with async functions -------------- */
  2490.  
  2491.  
  2492. /* This function is called when the alarm has gone off (but not from inside
  2493.  * the signal handler!). It schedules timer_cells->fm_refs for recalc. 
  2494.  */
  2495. #ifdef __STDC__
  2496. void
  2497. cell_alarm (void)
  2498. #else
  2499. void
  2500. cell_alarm ()
  2501. #endif
  2502. {
  2503.   int n;
  2504.   static time_t last_time = 0;
  2505.   if (timer_active)
  2506.     {
  2507.       time_t this_time = time(0);
  2508.       if ((this_time - last_time) < cell_timer_seconds)
  2509.     return;
  2510.       last_time = this_time;
  2511.       current_cycle++;
  2512.       for (n = 0; n < timer_cells->refs_used; n++)
  2513.     push_cell (timer_cells->fm_refs[n].ref_row,
  2514.            timer_cells->fm_refs[n].ref_col);
  2515.     }
  2516. }
  2517.  
  2518. /* All the timer_cells are going away, 'cuz everything is going away. . . */
  2519. #ifdef __STDC__
  2520. void
  2521. flush_all_timers (void)
  2522. #else
  2523. void
  2524. flush_all_timers ()
  2525. #endif
  2526. {
  2527.   if (timer_active)
  2528.     {
  2529. #ifdef SPLIT_REFS
  2530.       timer_cells->refs_used = 0;
  2531. #else
  2532.       flush_fm_ref (timer_cells);
  2533.       timer_cells = 0;
  2534. #endif
  2535.       timer_active = 0;
  2536.     }
  2537. }
  2538.  
  2539. /* Add CUR_ROW, CUR_COL to the list of active timer-cells, turning on
  2540.    the timer_active, if it isn't already */
  2541. #ifdef __STDC__
  2542. void
  2543. add_timer_ref (int whereto)
  2544. #else
  2545. void
  2546. add_timer_ref (whereto)
  2547.      int whereto;
  2548. #endif
  2549. {
  2550.   add_ref_to (whereto);
  2551.   add_ref_fm (&timer_cells, cur_row, cur_col);
  2552.   ++timer_active;
  2553. }
  2554.  
  2555. /* ---------- Routines and vars for dealing with the eval FIFO ------------ */
  2556. static struct cell_buf cell_buffer;
  2557.  
  2558. /* Start up the FIFO of cells to update */
  2559. #ifdef __STDC__
  2560. void
  2561. init_refs (void)
  2562. #else
  2563. void
  2564. init_refs ()
  2565. #endif
  2566. {
  2567.   cell_buffer.size = FIFO_START;
  2568.   cell_buffer.buf = (struct pos *) ck_malloc (cell_buffer.size * sizeof (struct pos));
  2569.   bzero (cell_buffer.buf, cell_buffer.size * sizeof (struct pos));
  2570.   cell_buffer.push_to_here = cell_buffer.buf;
  2571.   cell_buffer.pop_frm_here = cell_buffer.buf;
  2572.   the_vars = hash_new ();
  2573. }
  2574.  
  2575. /* Push the cells in REF onto the FIFO.  This calls push_cell to do the
  2576.    actual work. . . */
  2577. #ifdef __STDC__
  2578. void
  2579. push_refs (struct ref_fm *ref)
  2580. #else
  2581. void
  2582. push_refs (ref)
  2583.      struct ref_fm *ref;
  2584. #endif
  2585. {
  2586.   int n;
  2587.  
  2588.   if (!ref || !ref->refs_used)
  2589.     return;
  2590.   n = ref->refs_used;
  2591.   while (n--)
  2592.     {
  2593. #ifdef TEST
  2594.       CELL *cp;
  2595.  
  2596.       if (debug & 04)
  2597.     io_error_msg ("Push %s", cell_name (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col));
  2598.       cp = find_cell (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col);
  2599.       if (cp->cell_cycle == current_cycle)
  2600.     {
  2601.       if (debug & 01)
  2602.         io_error_msg ("Cycle detected from %s to %s",
  2603.               cell_name (cur_row, cur_col),
  2604.           cell_name (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col));
  2605.       push_cell (ref->fm_refs[n].ref_row,
  2606.              ref->fm_refs[n].ref_col);
  2607.     }
  2608.       else
  2609. #endif
  2610.     push_cell (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col);
  2611.     }
  2612. }
  2613.  
  2614. /* Push a cell onto the FIFO of cells to evaluate, checking for cells
  2615.    that are already on the FIFO, etc.
  2616.  
  2617.    This does not implement best-order recalculation, since there may be
  2618.    intersecting branches in the dependency tree, however, it's close enough
  2619.    for most people.
  2620.  */
  2621. #ifdef __STDC__
  2622. void
  2623. push_cell (CELLREF row, CELLREF col)
  2624. #else
  2625. void
  2626. push_cell (row, col)
  2627.      CELLREF row;
  2628.      CELLREF col;
  2629. #endif
  2630. {
  2631.   struct pos *dup;
  2632.   CELL *cp;
  2633.   struct ref_fm *rf;
  2634.  
  2635.   if (cell_buffer.push_to_here + 1 == cell_buffer.pop_frm_here || (cell_buffer.pop_frm_here == cell_buffer.buf && cell_buffer.push_to_here == cell_buffer.buf + (cell_buffer.size - 1)))
  2636.     {
  2637.       int f, t, from_num;
  2638.  
  2639.       f = cell_buffer.pop_frm_here - cell_buffer.buf;
  2640.       t = cell_buffer.push_to_here - cell_buffer.buf;
  2641.       from_num = cell_buffer.size - f;
  2642.  
  2643.       cell_buffer.size FIFO_INC;
  2644.       cell_buffer.buf = (struct pos *) ck_realloc ((VOIDSTAR) cell_buffer.buf, cell_buffer.size * sizeof (struct pos));
  2645.       if (t == 0)
  2646.     {
  2647.       cell_buffer.push_to_here = cell_buffer.buf + f + from_num;
  2648.       cell_buffer.pop_frm_here = cell_buffer.buf + f;
  2649.     }
  2650.       else if (t > f)
  2651.     {
  2652.       cell_buffer.push_to_here = cell_buffer.buf + t;
  2653.       cell_buffer.pop_frm_here = cell_buffer.buf + f;
  2654.     }
  2655.       else
  2656.     {
  2657.       cell_buffer.push_to_here = cell_buffer.buf + t;
  2658.       cell_buffer.pop_frm_here = cell_buffer.buf + (cell_buffer.size - from_num);
  2659.       if (from_num)
  2660.         bcopy (cell_buffer.buf + f,
  2661.            cell_buffer.pop_frm_here,
  2662.            from_num * sizeof (struct pos));
  2663.     }
  2664.     }
  2665.  
  2666. #if 1
  2667.   if (cell_buffer.pop_frm_here != cell_buffer.push_to_here)
  2668.     {
  2669.       dup = cell_buffer.pop_frm_here;
  2670.  
  2671.       cp = find_cell (row, col);
  2672.       if (!cp)
  2673.     {
  2674.       return;
  2675.     }
  2676.       rf = cp->cell_refs_from;
  2677.       for (; dup != cell_buffer.push_to_here;)
  2678.     {
  2679.       if (dup->row == row && dup->col == col)
  2680.         {
  2681. #ifdef TEST
  2682.           if (debug & 010)
  2683.         io_error_msg ("Flushed dup ref to %s", cell_name (row, col));
  2684. #endif
  2685.           *dup = *(cell_buffer.pop_frm_here);
  2686.           cell_buffer.pop_frm_here++;
  2687.           if (cell_buffer.pop_frm_here == cell_buffer.buf + cell_buffer.size)
  2688.         cell_buffer.pop_frm_here = cell_buffer.buf;
  2689.           break;
  2690.         }
  2691. #if 0
  2692.       if (rf)
  2693.         {
  2694.           for (n = 0; n < rf->refs_used; n++)
  2695.         if (rf->fm_refs[n].ref_row == dup->row && rf->fm_refs[n].ref_col == dup->col)
  2696.           {
  2697. #ifdef TEST
  2698.             if (debug & 01)
  2699.               io_error_msg ("Swapped %s and %s", cell_name (row, col), cell_name (dup->row, dup->col));
  2700. #endif
  2701.             dup->row = row;
  2702.             dup->col = col;
  2703.             row = rf->fm_refs[n].ref_row;
  2704.             col - rf->fm_refs[n].ref_col;
  2705.             goto breakout;
  2706.           }
  2707.         }
  2708. #endif
  2709.  
  2710.       if (++dup == cell_buffer.buf + cell_buffer.size)
  2711.         dup = cell_buffer.buf;
  2712.     }
  2713.     }
  2714. #endif
  2715.  
  2716.   cell_buffer.push_to_here->row = row;
  2717.   cell_buffer.push_to_here->col = col;
  2718.   cell_buffer.push_to_here++;
  2719.   if (cell_buffer.push_to_here == cell_buffer.buf + cell_buffer.size)
  2720.     cell_buffer.push_to_here = cell_buffer.buf;
  2721. }
  2722.  
  2723. /* Pop a cell off CELL_BUFFER, and evaluate it, displaying the result. . .
  2724.    This returns 0 if there are no more cells to update, or if it gets
  2725.    an error. */
  2726.  
  2727. #ifdef __STDC__
  2728. int
  2729. eval_next_cell (void)
  2730. #else
  2731. int
  2732. eval_next_cell ()
  2733. #endif
  2734. {
  2735.   CELL *cp;
  2736.   static loop_counter = 40;
  2737.  
  2738.   if (cell_buffer.pop_frm_here == cell_buffer.push_to_here)
  2739.     return 0;
  2740.  
  2741.   cur_row = cell_buffer.pop_frm_here->row;
  2742.   cur_col = cell_buffer.pop_frm_here->col;
  2743.   cell_buffer.pop_frm_here++;
  2744.   if (cell_buffer.pop_frm_here == cell_buffer.buf + cell_buffer.size)
  2745.     cell_buffer.pop_frm_here = cell_buffer.buf;
  2746.  
  2747.   cp = find_cell (cur_row, cur_col);
  2748.   if (cp)
  2749.     {
  2750.       if (cp->cell_cycle == current_cycle)
  2751.     --loop_counter;
  2752.       else
  2753.     loop_counter = 40;
  2754.       update_cell (cp);
  2755.       io_pr_cell (cur_row, cur_col, cp);
  2756.       return loop_counter;
  2757.     }
  2758.   else
  2759.     return 0;
  2760. }
  2761.  
  2762. #ifdef TEST
  2763. void
  2764. cell_buffer_contents ()
  2765. {
  2766.   struct pos *ptr;
  2767.  
  2768.   if (cell_buffer.pop_frm_here != cell_buffer.push_to_here)
  2769.     {
  2770.       ptr = cell_buffer.pop_frm_here;
  2771.       for (;;)
  2772.     {
  2773.       printf ("Ref to %s\r\n", cell_name (ptr->row, ptr->col));
  2774.       if (++ptr == cell_buffer.buf + cell_buffer.size)
  2775.         ptr = cell_buffer.buf;
  2776.       if (ptr == cell_buffer.push_to_here)
  2777.         break;
  2778.     }
  2779.     }
  2780.   printf ("End of buffer\r\n");
  2781. }
  2782.  
  2783. #endif
  2784.  
  2785. /* ----------------- Routines for dealing with variables ------------------ */
  2786.  
  2787. /* This sets the variable V_NAME to V_NEWVAL
  2788.    It returns error msg, or 0 on success.
  2789.    All the appropriate cells have their ref_fm arrays adjusted appropriatly
  2790.    This could be smarter; when changing a range var, only the cells that
  2791.    were in the old value but not in the new one need their references flushed,
  2792.    and only the cells that are new need references added.
  2793.    This might also be changed to use add_range_ref()?
  2794.  */
  2795. #ifdef __STDC__
  2796. char *
  2797. new_var_value (char *v_name, int v_namelen, char *v_newval)
  2798. #else
  2799. char *
  2800. new_var_value (v_name, v_namelen, v_newval)
  2801.      char *v_name;
  2802.      int v_namelen;
  2803.      char *v_newval;
  2804. #endif
  2805. {
  2806.   struct var *var;
  2807.   int n;
  2808.   int newflag;
  2809.   struct rng tmp_rng;
  2810.  
  2811.   cur_row = MIN_ROW;
  2812.   cur_col = MIN_COL;
  2813.   if (v_newval && *v_newval)
  2814.     {
  2815.       n = parse_cell_or_range (&v_newval, &tmp_rng);
  2816.       if (!n)
  2817.     return "Can't parse cell or range";
  2818.       if (*v_newval)
  2819.     return "Junk after cell or range";
  2820.       newflag = ((n | ROWREL | COLREL) == (R_CELL | ROWREL | COLREL)) ? VAR_CELL : VAR_RANGE;
  2821.     }
  2822.   else
  2823.     {
  2824.       tmp_rng.lr = tmp_rng.hr = NON_ROW;
  2825.       tmp_rng.lc = tmp_rng.hc = NON_COL;
  2826.       newflag = VAR_UNDEF;
  2827.     }
  2828.  
  2829.   var = find_or_make_var (v_name, v_namelen);
  2830.  
  2831.   if (var->var_ref_fm)
  2832.     {
  2833.       if (var->var_flags != VAR_UNDEF)
  2834.     {
  2835.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2836.         {
  2837.           flush_range_ref (&(var->v_rng),
  2838.                    var->var_ref_fm->fm_refs[n].ref_row,
  2839.                    var->var_ref_fm->fm_refs[n].ref_col);
  2840.         }
  2841.     }
  2842.       var->v_rng = tmp_rng;
  2843.  
  2844.       if (var->v_rng.lr != NON_ROW)
  2845.     {
  2846.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2847.         {
  2848.           cur_row = var->var_ref_fm->fm_refs[n].ref_row;
  2849.           cur_col = var->var_ref_fm->fm_refs[n].ref_col;
  2850.           add_range_ref (&(var->v_rng));
  2851.         }
  2852.     }
  2853.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2854.     push_cell (var->var_ref_fm->fm_refs[n].ref_row,
  2855.            var->var_ref_fm->fm_refs[n].ref_col);
  2856.     }
  2857.   else
  2858.     var->v_rng = tmp_rng;
  2859.  
  2860.   var->var_flags = newflag;
  2861.  
  2862.   return 0;
  2863. }
  2864.  
  2865. #ifdef __STDC__
  2866. void
  2867. for_all_vars (void (*func) (char *, struct var *))
  2868. #else
  2869. void
  2870. for_all_vars (func)
  2871.      void (*func) ();
  2872. #endif
  2873. {
  2874.   hash_apply (the_vars, func);
  2875. }
  2876.  
  2877. /* Find a variable in the list of variables, or create it if it doesn't
  2878.    exist.  Takes a name and a length so the name doesn't have to be
  2879.    null-terminated
  2880.  */
  2881. #ifdef __STDC__
  2882. struct var *
  2883. find_or_make_var (char *string, int len)
  2884. #else
  2885. struct var *
  2886. find_or_make_var (string, len)
  2887.      char *string;
  2888.      int len;
  2889. #endif
  2890. {
  2891.   struct var *ret;
  2892.   int ch;
  2893.  
  2894.   ch = string[len];
  2895.   string[len] = '\0';
  2896.  
  2897.   ret = (struct var *) hash_find (the_vars, string);
  2898.   if (ret)
  2899.     {
  2900.       string[len] = ch;
  2901.       return ret;
  2902.     }
  2903.  
  2904.   ret = (struct var *) ck_malloc (sizeof (struct var) + len);
  2905.   bcopy (string, ret->var_name, len + 1);
  2906.   ret->var_flags = VAR_UNDEF;
  2907.   ret->v_rng.lr = 0;
  2908.   ret->v_rng.lc = 0;
  2909.   ret->v_rng.hr = 0;
  2910.   ret->v_rng.hc = 0;
  2911.   ret->var_ref_fm = 0;
  2912.   hash_insert (the_vars, ret->var_name, ret);
  2913.   string[len] = ch;
  2914.   return ret;
  2915. }
  2916.  
  2917. /* Like find-or-make-var except returns 0 if it doesn't exist */
  2918. #ifdef __STDC__
  2919. struct var *
  2920. find_var (char *string, int len)
  2921. #else
  2922. struct var *
  2923. find_var (string, len)
  2924.      char *string;
  2925.      int len;
  2926. #endif
  2927. {
  2928.   int ch;
  2929.   struct var *ret;
  2930.  
  2931.   ch = string[len];
  2932.   string[len] = '\0';
  2933.   ret = (struct var *) hash_find (the_vars, string);
  2934.   string[len] = ch;
  2935.   return ret;
  2936. }
  2937.  
  2938. /* This adds a reference from CUR_ROW,CUR_COL to the variable VAR
  2939.    It calls add_ref or add_range_ref to have the cell(s) in VAR be
  2940.    referenced by CUR_ROW,CUR_COL
  2941.  */
  2942. #ifdef __STDC__
  2943. void
  2944. add_var_ref (void * vvar)
  2945. #else
  2946. void
  2947. add_var_ref (vvar)
  2948.      void * vvar;
  2949. #endif
  2950. {
  2951.   struct var *var = (struct var *)vvar;
  2952.   add_ref_fm (&(var->var_ref_fm), cur_row, cur_col);
  2953.   switch (var->var_flags)
  2954.     {
  2955.     case VAR_UNDEF:
  2956.       break;
  2957.     case VAR_CELL:
  2958.       add_ref (var->v_rng.lr, var->v_rng.lc);
  2959.       break;
  2960.     case VAR_RANGE:
  2961.       add_range_ref (&(var->v_rng));
  2962.       break;
  2963. #ifdef TEST
  2964.     default:
  2965.       panic ("Unknown var type %d in add_var_ref", var->var_flags);
  2966. #endif
  2967.     }
  2968. }
  2969.  
  2970. #ifdef __STDC__
  2971. static void
  2972. flush_var (char *name, struct var *var)
  2973. #else
  2974. static void
  2975. flush_var (name, var)
  2976.      char *name;
  2977.      struct var *var;
  2978. #endif
  2979. {
  2980. #ifdef SPLIT_REFS
  2981.   if (var->var_ref_fm)
  2982.     free (var->var_ref_fm);
  2983. #endif
  2984.   free (var);
  2985. }
  2986.  
  2987.  
  2988. /* Free up all the variables, and (if SPLIT_REFS) the ref_fm structure
  2989.    associated with each variable.  Note that this does not get rid of
  2990.    the struct var *s in cell expressions, so it can only be used when all
  2991.    the cells are being freed also
  2992.  */
  2993. #ifdef __STDC__
  2994. void
  2995. flush_variables (void)
  2996. #else
  2997. void
  2998. flush_variables ()
  2999. #endif
  3000. {
  3001.   for_all_vars (flush_var);
  3002.   hash_die (the_vars);
  3003.   the_vars = hash_new ();
  3004. }
  3005.